浏览代码

Added Ray.Gui. Fixed bool issues.

Added more examples.
Brucey 5 年之前
父节点
当前提交
9036401c7e
共有 100 个文件被更改,包括 9793 次插入0 次删除
  1. 81 0
      gui.mod/common.bmx
  2. 25 0
      gui.mod/glue.c
  3. 348 0
      gui.mod/gui.bmx
  4. 1 0
      gui.mod/raygui/.gitattributes
  5. 12 0
      gui.mod/raygui/.github/FUNDING.yml
  6. 62 0
      gui.mod/raygui/.gitignore
  7. 17 0
      gui.mod/raygui/HISTORY.md
  8. 18 0
      gui.mod/raygui/LICENSE
  9. 73 0
      gui.mod/raygui/README.md
  10. 388 0
      gui.mod/raygui/examples/Makefile
  11. 245 0
      gui.mod/raygui/examples/controls_test_suite/controls_test_suite.c
  12. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/FiveByFive10.ttf
  13. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/NorthernLights.ttf
  14. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/PIXEARG11.ttf
  15. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/PixelOperator8.ttf
  16. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/pixelpoiiz10.ttf
  17. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/prstartk8.ttf
  18. 二进制
      gui.mod/raygui/examples/controls_test_suite/fonts/rainyhearts16.ttf
  19. 二进制
      gui.mod/raygui/examples/custom_file_dialog/cat.png
  20. 113 0
      gui.mod/raygui/examples/custom_file_dialog/custom_file_dialog.c
  21. 558 0
      gui.mod/raygui/examples/custom_file_dialog/gui_file_dialog.h
  22. 195 0
      gui.mod/raygui/examples/image_exporter/image_exporter.c
  23. 二进制
      gui.mod/raygui/examples/image_exporter/resources/cat.png
  24. 二进制
      gui.mod/raygui/examples/image_exporter/resources/fudesumi.png
  25. 二进制
      gui.mod/raygui/examples/image_exporter/resources/parrots.png
  26. 二进制
      gui.mod/raygui/examples/image_exporter/resources/scarfy.png
  27. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REF.png
  28. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV0.png
  29. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV1.png
  30. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV2.png
  31. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV3.png
  32. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV4.png
  33. 二进制
      gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV5.png
  34. 二进制
      gui.mod/raygui/examples/image_raw_importer/image_2x2_RGBA.raw
  35. 230 0
      gui.mod/raygui/examples/image_raw_importer/image_raw_importer.c
  36. 96 0
      gui.mod/raygui/examples/portable_window/portable_window.c
  37. 150 0
      gui.mod/raygui/examples/scroll_panel/gui_scroll_panel.c
  38. 193 0
      gui.mod/raygui/examples/standalone/custom_backend.h
  39. 36 0
      gui.mod/raygui/examples/standalone/raygui_standalone.c
  40. 301 0
      gui.mod/raygui/examples/text_box_selection/textbox_extended_demo.c
  41. 297 0
      gui.mod/raygui/examples/text_editor/text_editor.c
  42. 二进制
      gui.mod/raygui/images/raygui_controls_panel.png
  43. 二进制
      gui.mod/raygui/images/raygui_ricons.png
  44. 二进制
      gui.mod/raygui/images/raygui_style_table_multi.png
  45. 二进制
      gui.mod/raygui/images/rguistyler_v210.png
  46. 二进制
      gui.mod/raygui/images/rguistyler_v300.png
  47. 二进制
      gui.mod/raygui/logo/raygui.ico
  48. 二进制
      gui.mod/raygui/logo/raygui_128x128.png
  49. 二进制
      gui.mod/raygui/logo/raygui_16x16.png
  50. 二进制
      gui.mod/raygui/logo/raygui_24x24.png
  51. 二进制
      gui.mod/raygui/logo/raygui_256x256.png
  52. 二进制
      gui.mod/raygui/logo/raygui_32x32.png
  53. 二进制
      gui.mod/raygui/logo/raygui_48x48.png
  54. 二进制
      gui.mod/raygui/logo/raygui_64x64.png
  55. 二进制
      gui.mod/raygui/logo/raygui_96x96.png
  56. 182 0
      gui.mod/raygui/projects/VS2017/examples/controls_test_suite.vcxproj
  57. 55 0
      gui.mod/raygui/projects/VS2017/raygui.sln
  58. 192 0
      gui.mod/raygui/projects/VS2017/raylib/raylib.vcxproj
  59. 1072 0
      gui.mod/raygui/src/gui_textbox_extended.h
  60. 3701 0
      gui.mod/raygui/src/raygui.h
  61. 556 0
      gui.mod/raygui/src/ricons.h
  62. 36 0
      gui.mod/raygui/styles/README.md
  63. 16 0
      gui.mod/raygui/styles/ashes/README.md
  64. 24 0
      gui.mod/raygui/styles/ashes/ashes.rgs
  65. 51 0
      gui.mod/raygui/styles/ashes/font_readme.txt
  66. 二进制
      gui.mod/raygui/styles/ashes/screenshot.png
  67. 二进制
      gui.mod/raygui/styles/ashes/style_table.png
  68. 二进制
      gui.mod/raygui/styles/ashes/v5loxical.ttf
  69. 16 0
      gui.mod/raygui/styles/bluish/README.md
  70. 24 0
      gui.mod/raygui/styles/bluish/bluish.rgs
  71. 76 0
      gui.mod/raygui/styles/bluish/font_readme.txt
  72. 二进制
      gui.mod/raygui/styles/bluish/homespun.ttf
  73. 二进制
      gui.mod/raygui/styles/bluish/screenshot.png
  74. 二进制
      gui.mod/raygui/styles/bluish/style_table.png
  75. 16 0
      gui.mod/raygui/styles/candy/README.md
  76. 24 0
      gui.mod/raygui/styles/candy/candy.rgs
  77. 27 0
      gui.mod/raygui/styles/candy/font_readme.txt
  78. 二进制
      gui.mod/raygui/styles/candy/screenshot.png
  79. 二进制
      gui.mod/raygui/styles/candy/style_table.png
  80. 二进制
      gui.mod/raygui/styles/candy/v5easter.ttf
  81. 16 0
      gui.mod/raygui/styles/cherry/README.md
  82. 二进制
      gui.mod/raygui/styles/cherry/Westington.ttf
  83. 24 0
      gui.mod/raygui/styles/cherry/cherry.rgs
  84. 二进制
      gui.mod/raygui/styles/cherry/screenshot.png
  85. 二进制
      gui.mod/raygui/styles/cherry/style_table.png
  86. 二进制
      gui.mod/raygui/styles/cyber/Kyrou 7 Wide.ttf
  87. 16 0
      gui.mod/raygui/styles/cyber/README.md
  88. 24 0
      gui.mod/raygui/styles/cyber/cyber.rgs
  89. 36 0
      gui.mod/raygui/styles/cyber/font_readme.txt
  90. 二进制
      gui.mod/raygui/styles/cyber/screenshot.png
  91. 二进制
      gui.mod/raygui/styles/cyber/style_table.png
  92. 14 0
      gui.mod/raygui/styles/default/README.md
  93. 69 0
      gui.mod/raygui/styles/default/default.rgs
  94. 二进制
      gui.mod/raygui/styles/default/screenshot.png
  95. 二进制
      gui.mod/raygui/styles/default/style_table.png
  96. 二进制
      gui.mod/raygui/styles/jungle/Pixel Intv.otf
  97. 16 0
      gui.mod/raygui/styles/jungle/README.md
  98. 47 0
      gui.mod/raygui/styles/jungle/font_readme.txt
  99. 24 0
      gui.mod/raygui/styles/jungle/jungle.rgs
  100. 二进制
      gui.mod/raygui/styles/jungle/screenshot.png

+ 81 - 0
gui.mod/common.bmx

@@ -0,0 +1,81 @@
+' Copyright (c) 2020 Bruce A Henderson
+'
+' This software is provided 'as-is', without any express or implied
+' warranty. In no event will the authors be held liable for any damages
+' arising from the use of this software.
+'
+' Permission is granted to anyone to use this software for any purpose,
+' including commercial applications, and to alter it and redistribute it
+' freely, subject to the following restrictions:
+'
+'    1. The origin of this software must not be misrepresented; you must not
+'    claim that you wrote the original software. If you use this software
+'    in a product, an acknowledgment in the product documentation would be
+'    appreciated but is not required.
+'
+'    2. Altered source versions must be plainly marked as such, and must not be
+'    misrepresented as being the original software.
+'
+'    3. This notice may not be removed or altered from any source
+'    distribution.
+'
+SuperStrict
+
+Import Ray.Lib
+Import "source.bmx"
+
+Extern
+
+	Function bmx_raygui_GuiEnable()="GuiEnable"
+	Function bmx_raygui_GuiDisable()="GuiDisable"
+	Function bmx_raygui_GuiLock()="GuiLock"
+	Function bmx_raygui_GuiUnlock()="GuiUnlock"
+	Function bmx_raygui_GuiFade(alpha:Float)="GuiFade"
+
+	Function bmx_raygui_GuiSetState(state:Int)="GuiSetState"
+	Function bmx_raygui_GuiGetState:Int()="GuiGetState"
+
+	Function bmx_raygui_GuiSetFont(font:RFont)="GuiSetFont"
+	Function bmx_raygui_GuiGetFont:RFont()="GuiGetFont"
+
+	Function bmx_raygui_GuiSetStyle(control:Int, property:Int, value:Int)="GuiSetStyle"
+	Function bmx_raygui_GuiGetStyle:Int(control:Int, property:Int)="GuiGetStyle"
+
+	Function bmx_raygui_GuiWindowBox:Int(bounds:RRectangle, title:Byte Ptr)="GuiWindowBox"
+	Function bmx_raygui_GuiGroupBox(bounds:RRectangle, txt:Byte Ptr)="GuiGroupBox"
+	Function bmx_raygui_GuiLine(bounds:RRectangle, txt:Byte Ptr)="GuiLine"
+	Function bmx_raygui_GuiPanel(bounds:RRectangle)="GuiPanel"
+	Function bmx_raygui_GuiScrollPanel:RRectangle(bounds:RRectangle, content:RRectangle, scroll:RVector2 Var)="GuiScrollPanel"
+
+	Function bmx_raygui_GuiLabel(bounds:RRectangle, txt:Byte Ptr)="GuiLabel"
+	Function bmx_raygui_GuiButton:Int(bounds:RRectangle, txt:Byte Ptr)="GuiButton"
+	Function bmx_raygui_GuiLabelButton:Int(bounds:RRectangle, txt:Byte Ptr)="GuiLabelButton"
+	Function bmx_raygui_GuiImageButton:Int(bounds:RRectangle, txt:Byte Ptr, texture:RTexture2D)="GuiImageButton"
+	Function bmx_raygui_GuiImageButtonEx:Int(bounds:RRectangle, txt:Byte Ptr, texture:RTexture2D, texSource:RRectangle)="GuiImageButtonEx"
+	Function bmx_raygui_GuiToggle:Int(bounds:RRectangle, txt:Byte Ptr, active:Int)="GuiToggle"
+	Function bmx_raygui_GuiToggleGroup:Int(bounds:RRectangle, txt:Byte Ptr, active:Int)="GuiToggleGroup"
+	Function bmx_raygui_GuiCheckBox:Int(bounds:RRectangle, txt:Byte Ptr, checked:Int)="GuiCheckBox"
+	Function bmx_raygui_GuiComboBox:Int(bounds:RRectangle, txt:Byte Ptr, active:Int)="GuiComboBox"
+	Function bmx_raygui_GuiDropdownBox:Int(bounds:RRectangle, txt:Byte Ptr, active:Int Var, editMode:Int)="GuiDropdownBox"
+	Function bmx_raygui_GuiSpinner:Int(bounds:RRectangle, txt:Byte Ptr, value:Int Var, minValue:Int, maxValue:Int, editMode:Int)="GuiSpinner"
+	Function bmx_raygui_GuiValueBox:Int(bounds:RRectangle, txt:Byte Ptr, value:Int Var, minValue:Int, maxValue:Int, editMode:Int)="GuiValueBox"
+	Function bmx_raygui_GuiTextBox:Int(bounds:RRectangle, txt:Byte Ptr, textSize:Int, editMode:Int)="GuiTextBox"
+	Function bmx_raygui_GuiTextBoxMulti:Int(bounds:RRectangle, txt:Byte Ptr, textSize:Int, editMode:Int)="GuiTextBoxMulti"
+	Function bmx_raygui_GuiSlider:Float(bounds:RRectangle, txtLeft:Byte Ptr, txtRight:Byte Ptr, value:Float, minValue:Float, maxValue:Float)="GuiSlider"
+	Function bmx_raygui_GuiSliderBar:Float(bounds:RRectangle, txtLeft:Byte Ptr, txtRight:Byte Ptr, value:Float, minValue:Float, maxValue:Float)="GuiSliderBar"
+	Function bmx_raygui_GuiProgressBar:Float(bounds:RRectangle, txtLeft:Byte Ptr, txtRight:Byte Ptr, value:Float, minValue:Float, maxValue:Float)="GuiProgressBar"
+	Function bmx_raygui_GuiStatusBar(bounds:RRectangle, txt:Byte Ptr)="GuiStatusBar"
+	Function bmx_raygui_GuiDummyRec(bounds:RRectangle, txt:Byte Ptr)="GuiDummyRec"
+	Function bmx_raygui_GuiScrollBar:Int(bounds:RRectangle, value:Int, minValue:Int, maxValue:Int)="GuiScrollBar"
+	Function bmx_raygui_GuiGrid:RVector2(bounds:RRectangle, spacing:Float, subdivs:Int)="GuiGrid"
+
+	Function bmx_raygui_GuiListView:Int(bounds:RRectangle, txt:Byte Ptr, scrollIndex:Int Var, active:Int)="GuiListView"
+	Function bmx_raygui_GuiListViewEx:Int(bounds:RRectangle, txt:Size_T Ptr, focus:Int Var, scrollIndex:Int Var, active:Int)="GuiListViewEx"
+	Function bmx_raygui_GuiMessageBox:Int(bounds:RRectangle, title:Byte Ptr, message:Byte Ptr, buttons:Byte Ptr)="GuiMessageBox"
+	Function bmx_raygui_GuiColorPicker:RColor(bounds:RRectangle, color:RColor)="GuiColorPicker"
+	Function bmx_raygui_GuiTextInputBox:Int(bounds:RRectangle, title:Byte Ptr, message:Byte Ptr, buttons:Byte Ptr, txt:Byte Ptr)="GuiTextInputBox"
+
+	Function bmx_raygui_GuiLoadStyle(fileName:Byte Ptr)="GuiLoadStyle"
+	Function bmx_raygui_GuiLoadStyleDefault()="GuiLoadStyleDefault"
+
+End Extern

+ 25 - 0
gui.mod/glue.c

@@ -0,0 +1,25 @@
+/*
+  Copyright (c) 2020 Bruce A Henderson
+
+  This software is provided 'as-is', without any express or implied
+  warranty. In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+     1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+
+     2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+
+     3. This notice may not be removed or altered from any source
+     distribution.
+*/
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_ICONS
+#include "raygui.h"

+ 348 - 0
gui.mod/gui.bmx

@@ -0,0 +1,348 @@
+' Copyright (c) 2020 Bruce A Henderson
+'
+' This software is provided 'as-is', without any express or implied
+' warranty. In no event will the authors be held liable for any damages
+' arising from the use of this software.
+'
+' Permission is granted to anyone to use this software for any purpose,
+' including commercial applications, and to alter it and redistribute it
+' freely, subject to the following restrictions:
+'
+'    1. The origin of this software must not be misrepresented; you must not
+'    claim that you wrote the original software. If you use this software
+'    in a product, an acknowledgment in the product documentation would be
+'    appreciated but is not required.
+'
+'    2. Altered source versions must be plainly marked as such, and must not be
+'    misrepresented as being the original software.
+'
+'    3. This notice may not be removed or altered from any source
+'    distribution.
+'
+SuperStrict
+
+Module Ray.GUI
+
+Import "common.bmx"
+
+
+
+
+Function GuiEnable()
+	bmx_raygui_GuiEnable()
+End Function
+
+Function GuiDisable()
+	bmx_raygui_GuiDisable()
+End Function
+
+Function GuiLock()
+	bmx_raygui_GuiLock()
+End Function
+
+Function GuiUnlock()
+	bmx_raygui_GuiUnlock()
+End Function
+
+Function GuiFade(alpha:Float)
+	bmx_raygui_GuiFade(alpha)
+End Function
+
+
+Function GuiSetState(state:Int)
+	bmx_raygui_GuiSetState(state)
+End Function
+
+Function GuiGetState:Int()
+	Return bmx_raygui_GuiGetState()
+End Function
+
+
+Function GuiSetFont(font:RFont)
+	bmx_raygui_GuiSetFont(font)
+End Function
+
+Function GuiGetFont:RFont()
+	bmx_raygui_GuiGetFont()
+End Function
+
+
+' Style set/get functions
+Function GuiSetStyle(control:Int, property:Int, value:Int)
+	bmx_raygui_GuiSetStyle(control, property, value)
+End Function
+
+Function GuiGetStyle:Int(control:Int, property:Int)
+	bmx_raygui_GuiGetStyle(control, property)
+End Function
+
+
+' Container/separator controls, useful for controls organization
+Function GuiWindowBox:Int(bounds:RRectangle, title:String)
+	Local length:Size_T = title.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	title.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiWindowBox(bounds, t)
+End Function
+
+Function GuiGroupBox(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	bmx_raygui_GuiGroupBox(bounds, t)
+End Function
+
+Function GuiLine(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	bmx_raygui_GuiLine(bounds, t)
+End Function
+
+Function GuiPanel(bounds:RRectangle)
+	bmx_raygui_GuiPanel(bounds)
+End Function
+
+Function GuiScrollPanel:RRectangle(bounds:RRectangle, content:RRectangle, scroll:RVector2 Var)
+	Return bmx_raygui_GuiScrollPanel(bounds, content, scroll)
+End Function
+
+
+' Basic controls set
+Function GuiLabel(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	bmx_raygui_GuiLabel(bounds:RRectangle, t)
+End Function
+
+Function GuiButton:Int(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiButton(bounds:RRectangle, t)
+End Function
+
+Function GuiLabelButton:Int(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiLabelButton(bounds:RRectangle, t)
+End Function
+
+Function GuiImageButton:Int(bounds:RRectangle, txt:String, texture:RTexture2D)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiImageButton(bounds, t, texture)
+End Function
+
+Function GuiImageButtonEx:Int(bounds:RRectangle, txt:String, texture:RTexture2D, texSource:RRectangle)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiImageButtonEx(bounds, t, texture, texSource)
+End Function
+
+Function GuiToggle:Int(bounds:RRectangle, txt:String, active:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiToggle(bounds, t, active)
+End Function
+
+Function GuiToggleGroup:Int(bounds:RRectangle, txt:String, active:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiToggleGroup(bounds, t, active)
+End Function
+
+Function GuiCheckBox:Int(bounds:RRectangle, txt:String, checked:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiCheckBox(bounds, t, checked)
+End Function
+
+Function GuiComboBox:Int(bounds:RRectangle, txt:String, active:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiComboBox(bounds, t, active)
+End Function
+
+Function GuiDropdownBox:Int(bounds:RRectangle, txt:String, active:Int Var, editMode:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiDropdownBox(bounds, t, active, editMode)
+End Function
+
+Function GuiSpinner:Int(bounds:RRectangle, txt:String, value:Int Var, minValue:Int, maxValue:Int, editMode:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiSpinner(bounds, t, value, minValue, maxValue, editMode)
+End Function
+
+Function GuiValueBox:Int(bounds:RRectangle, txt:String, value:Int Var, minValue:Int, maxValue:Int, editMode:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Return bmx_raygui_GuiValueBox(bounds, t, value, minValue, maxValue, editMode)
+End Function
+
+Function GuiTextBox:Int(bounds:RRectangle, txt:String Var, textSize:Int, editMode:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Local res:Int = bmx_raygui_GuiTextBox(bounds, t, textSize, editMode)
+	txt = String.FromUTF8String(t)
+	Return res
+End Function
+
+Function GuiTextBoxMulti:Int(bounds:RRectangle, txt:String Var, textSize:Int, editMode:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	Local res:Int = bmx_raygui_GuiTextBoxMulti(bounds, t, textSize, editMode)
+	txt = String.FromUTF8String(t)
+	Return res
+End Function
+
+Function GuiSlider:Float(bounds:RRectangle, txtLeft:String, txtRight:String, value:Float, minValue:Float, maxValue:Float)
+	Local length:Size_T = txtLeft.length * 3 + 1
+	Local tl:Byte Ptr = StackAlloc(length)
+	txtLeft.ToUTF8StringBuffer(tl, length)
+
+	length = txtRight.length * 3 + 1
+	Local tr:Byte Ptr = StackAlloc(length)
+	txtRight.ToUTF8StringBuffer(tr, length)
+
+	Return bmx_raygui_GuiSlider(bounds, tl, tr, value, minValue, maxValue)
+End Function
+
+Function GuiSliderBar:Float(bounds:RRectangle, txtLeft:String, txtRight:String, value:Float, minValue:Float, maxValue:Float)
+	Local length:Size_T = txtLeft.length * 3 + 1
+	Local tl:Byte Ptr = StackAlloc(length)
+	txtLeft.ToUTF8StringBuffer(tl, length)
+
+	length = txtRight.length * 3 + 1
+	Local tr:Byte Ptr = StackAlloc(length)
+	txtRight.ToUTF8StringBuffer(tr, length)
+
+	Return bmx_raygui_GuiSliderBar(bounds, tl, tr, value, minValue, maxValue)
+End Function
+
+Function GuiProgressBar:Float(bounds:RRectangle, txtLeft:String, txtRight:String, value:Float, minValue:Float, maxValue:Float)
+	Local length:Size_T = txtLeft.length * 3 + 1
+	Local tl:Byte Ptr = StackAlloc(length)
+	txtLeft.ToUTF8StringBuffer(tl, length)
+
+	length = txtRight.length * 3 + 1
+	Local tr:Byte Ptr = StackAlloc(length)
+	txtRight.ToUTF8StringBuffer(tr, length)
+
+	Return bmx_raygui_GuiProgressBar(bounds, tl, tr, value, minValue, maxValue)
+End Function
+
+Function GuiStatusBar(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	bmx_raygui_GuiStatusBar(bounds, t)
+End Function
+
+Function GuiDummyRec(bounds:RRectangle, txt:String)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+	bmx_raygui_GuiDummyRec(bounds, t)
+End Function
+
+Function GuiScrollBar:Int(bounds:RRectangle, value:Int, minValue:Int, maxValue:Int)
+	Return bmx_raygui_GuiScrollBar(bounds, value, minValue, maxValue)
+End Function
+
+Function GuiGrid:RVector2(bounds:RRectangle, spacing:Float, subdivs:Int)
+	Return bmx_raygui_GuiGrid(bounds:RRectangle, spacing, subdivs)
+End Function
+
+
+' Advance controls set
+Function GuiListView:Int(bounds:RRectangle, txt:String, scrollIndex:Int Var, active:Int)
+	Local length:Size_T = txt.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	txt.ToUTF8StringBuffer(t, length)
+
+	Return bmx_raygui_GuiListView(bounds:RRectangle, t, scrollIndex, active)
+End Function
+
+Function GuiListViewEx:Int(bounds:RRectangle, txt:String[], focus:Int Var, scrollIndex:Int Var, active:Int)
+	Local list:Size_T Ptr = MemAlloc(Size_T(txt.length * 8))
+	For Local i:Int = 0 Until txt.length
+		list[i] = Size_T(txt[i].ToUTF8String())
+	Next
+	Local res:Int = bmx_raygui_GuiListViewEx(bounds, list, focus, scrollIndex, active)
+	For Local i:Int = 0 Until txt.length
+		MemFree(Byte Ptr(list[i]))
+	Next
+	MemFree(list)
+	Return res
+End Function
+
+Function GuiMessageBox:Int(bounds:RRectangle, title:String, message:String, buttons:String)
+	Local length:Size_T = title.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	title.ToUTF8StringBuffer(t, length)
+
+	length = message.length * 3 + 1
+	Local m:Byte Ptr = StackAlloc(length)
+	message.ToUTF8StringBuffer(m, length)
+
+	length = buttons.length * 3 + 1
+	Local b:Byte Ptr = StackAlloc(length)
+	buttons.ToUTF8StringBuffer(b, length)
+	
+	Return bmx_raygui_GuiMessageBox(bounds, t, m, b)
+End Function
+
+Function GuiColorPicker:RColor(bounds:RRectangle, color:RColor)
+	Return bmx_raygui_GuiColorPicker(bounds, color)
+End Function
+
+Function GuiTextInputBox:Int(bounds:RRectangle, title:String, message:String, buttons:String, txt:String)
+	Local length:Size_T = title.length * 3 + 1
+	Local t:Byte Ptr = StackAlloc(length)
+	title.ToUTF8StringBuffer(t, length)
+
+	length = message.length * 3 + 1
+	Local m:Byte Ptr = StackAlloc(length)
+	message.ToUTF8StringBuffer(m, length)
+
+	length = buttons.length * 3 + 1
+	Local b:Byte Ptr = StackAlloc(length)
+	buttons.ToUTF8StringBuffer(b, length)
+
+	Local t2:Byte Ptr = txt.ToUTF8String()
+	Local res:Int = bmx_raygui_GuiTextInputBox(bounds, t, m, b, t2)
+	MemFree(t2)
+	
+	Return res
+End Function
+
+
+' Styles loading functions
+Function GuiLoadStyle(fileName:String)
+	Local length:Size_T = fileName.length * 3 + 1
+	Local f:Byte Ptr = StackAlloc(length)
+	fileName.ToUTF8StringBuffer(f, length)
+
+	bmx_raygui_GuiLoadStyle(f)
+End Function
+
+Function GuiLoadStyleDefault()
+	bmx_raygui_GuiLoadStyleDefault()
+End Function
+

+ 1 - 0
gui.mod/raygui/.gitattributes

@@ -0,0 +1 @@
+*.h linguist-language=C

+ 12 - 0
gui.mod/raygui/.github/FUNDING.yml

@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: raysan5
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

+ 62 - 0
gui.mod/raygui/.gitignore

@@ -0,0 +1,62 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+
+# VSCode files
+.vscode/
+
+
+# Ignore files build by Visual Studio
+[Dd]ebug
+[Rr]elease
+*.vs
+*.obj
+*.pdb
+*.aps
+*.user
+# *.vcproj
+# *.vcxproj*
+# *.sln
+*.vspscc
+*_i.c
+*.i
+*.icf
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log

+ 17 - 0
gui.mod/raygui/HISTORY.md

@@ -0,0 +1,17 @@
+## raygui history
+
+raygui development started on December 2014 by two internship students (Kevin and Daniel) guided by me, objective was creating a simple and easy-to-use immediate-mode-gui module for raylib, intended for tools development. On June 2015, library was mostly functional (including basic controls) and we started working in the styling posibilities for the library, focusing on an easy way to style controls properties. Consequently, development of [rGuiStyler](https://raylibtech.itch.io/rguistyler) also started at that point... but resources were quite limited and project was stopped for several months, most of the time was invested in [raylib](https://github.com/raysan5/raylib) development.
+
+On June 2016, project was picked up again and raygui 1.0 was released by the end of that month. During August 2016, raygui was used to develop [rFXGen](https://github.com/raysan5/rfxgen) and also an early protoype of [rGuiLayout](https://raylibtech.itch.io/rguilayout), those tools were a testbed for the library. By the end of 2016, raygui project development was stopped again for several months.
+
+On June 2017, a complete redesign of the library started, almost from scratch, all functions were reviewed and mostly rewritten and a brand new styling system was developed. The objective was using raygui professionally in several tools. It was the beginning of raygui 2.0.
+
+On January 2018, two students (Adria and Jordi) started working on raygui and related tools; library evolved considerably in the following months. [rGuiStyler](https://raylibtech.itch.io/rguistyler) was completely redesigned and rewritten from scratch (rGuiStyler v2.0). [rGuiLayout](https://raylibtech.itch.io/rguilayout) turned from a protoype into a professional software and raygui reached version 2.0 with plenty of new controls and features.
+
+On July 2018, I started working full time on raygui and its tools, improving the library considerably. On October 2018 [Sergio](https://github.com/anidealgift) joined the project and focused efforts on [rGuiLayout](https://raylibtech.itch.io/rguilayout) tool redesign. We reached 2019 with continuous improvement and redesigns of mostly all raygui functions along rGuiLayout 2.0 and rGuiStyler 3.0.
+
+On March 2019, the first set of new raygui tools was published: [rFXGen 2.0](https://raylibtech.itch.io/rfxgen), [rTexViewer 1.0](https://raylibtech.itch.io/rtexviewer) and [rIconPacker 1.0](https://raylibtech.itch.io/riconpacker).
+
+From March 2019 to June 2019 raygui development decelerated, Sergio left the project and efforts were focused on raylib 2.5, during this time one external contributor, [Vlad Adrian](https://github.com/Demizdor), completely redesigned `GuiTextBox()` and related controls and version was bumped to raygui 2.5.
+
+During summer 2019 lots of raygui functions were reviewed, breaking compatibility to any previous version and pointing to a **raygui 2.6** update.

+ 18 - 0
gui.mod/raygui/LICENSE

@@ -0,0 +1,18 @@
+zlib License
+	
+Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+
+This software is provided "as-is", without any express or implied warranty. In no event 
+will the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not claim that you 
+  wrote the original software. If you use this software in a product, an acknowledgment 
+  in the product documentation would be appreciated but is not required.
+
+  2. Altered source versions must be plainly marked as such, and must not be misrepresented
+  as being the original software.
+
+  3. This notice may not be removed or altered from any source distribution.

+ 73 - 0
gui.mod/raygui/README.md

@@ -0,0 +1,73 @@
+<img align="left" src="logo/raygui_256x256.png" width=256>
+
+**raygui** is a simple and easy-to-use immediate-mode-gui library.
+
+raygui was initially inspired by [Unity IMGUI](https://docs.unity3d.com/Manual/GUIScriptingGuide.html) (immediate mode GUI API).
+
+raygui was originated as an auxiliar module for [raylib](https://github.com/raysan5/raylib) to create simple GUI interfaces using raylib graphic style (simple colors, plain rectangular shapes, wide borders...).
+
+raygui is intended for **tools development**; it has already been used to develop the following tools: [rFXGen](https://github.com/raysan5/rfxgen), [rTexViewer](https://raylibtech.itch.io/rtexviewer), [rTexPacker](https://raylibtech.itch.io/rtexpacker) [rGuiStyler](https://raylibtech.itch.io/rguistyler), [rGuiLayout](https://raylibtech.itch.io/rguilayout) and [rGuiIcons](https://raylibtech.itch.io/rguiicons)
+
+<br>
+
+## raygui provided controls
+
+#### Container/separator controls
+```
+WindowBox   |  GroupBox    |  Line        |  Panel
+```
+#### Basic controls
+```
+Label       |  Button      |  LabelButton |  ImageButton  |  Toggle      |  ToggleGroup |  CheckBox
+ComboBox    |  DropdownBox |  TextBox     |  TextBoxMulti |  ValueBox    |  Spinner     |  Slider   
+SliderBar   |  ProgressBar |  StatusBar   |  ScrollBar    |  ScrollPanel |  DummyRec    |  Grid
+```
+#### Advance controls
+```
+ListView    |  ColorPicker |  MessageBox  |  TextInputBox
+```
+
+## raygui styles
+
+raygui comes with a [default](styles/default) style automatically loaded at runtime:
+
+![raygui default style](styles/default/style_table.png)
+
+Some additional styles are also provided for convenience, just check [styles directory](styles) for details:
+
+![raygui additional styles](images/raygui_style_table_multi.png)
+
+Custom styles can also be created very easily using [rGuiStyler](https://raylibtech.itch.io/rguistyler) tool. 
+
+Styles can be loaded at runtime using raygui `GuiLoadStyle()` function. Simple and easy-to-use.
+
+![rGuiStyler v3.1](images/rguistyler_v300.png)
+
+*rGuiStyler v3.1 - raygui styles editor, useful to create custom styles*
+ 
+## raygui icons
+
+`raygui` supports custom icons provided as an external array of data. To support icons just define `RAYGUI_SUPPORT_ICONS` before including `raygui`. 
+
+A set of custom handcrafter icons is provided in [`riconsdata`](src/riconsdata.h). This set of icons can be created and customized using [rGuiIcons](https://raylibtech.itch.io/rguiicons) tool.  
+
+<img align="right" src="images/raygui_ricons.png">
+
+```c
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_ICONS
+#include "raygui.h"
+```
+To use any of those icons in your gui, just preprend *iconId* to any text written within `raygui` controls:
+```c
+if (GuiButton(rec, "#05#Open Image") { /* ACTION */ }
+```
+or use the provided `GuiIconText()` function to prepend it automatically, using a clearer identifier.
+```c
+if (GuiButton(rec, GuiIconText(RICON_FILE_OPEN, "Open Image"))) { /* ACTION */ }
+```
+
+license
+-------
+
+raygui is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. Check [LICENSE](LICENSE.md) for further details.

+ 388 - 0
gui.mod/raygui/examples/Makefile

@@ -0,0 +1,388 @@
+#**************************************************************************************************
+#
+#   raylib makefile for Desktop platform and HTML5
+#
+#   Copyright (c) 2019 Ramon Santamaria (@raysan5)
+#
+#   This software is provided "as-is", without any express or implied warranty. In no event
+#   will the authors be held liable for any damages arising from the use of this software.
+#
+#   Permission is granted to anyone to use this software for any purpose, including commercial
+#   applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+#     1. The origin of this software must not be misrepresented; you must not claim that you
+#     wrote the original software. If you use this software in a product, an acknowledgment
+#     in the product documentation would be appreciated but is not required.
+#
+#     2. Altered source versions must be plainly marked as such, and must not be misrepresented
+#     as being the original software.
+#
+#     3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+.PHONY: all clean
+
+# Define required raylib variables
+RAYLIB_PATH        ?= ../../raylib
+RAYGUI_PATH        ?= ../src
+
+# Define default options
+
+# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+PLATFORM           ?= PLATFORM_DESKTOP
+
+# Locations of your newly installed library and associated headers. See ../src/Makefile
+# On Linux, if you have installed raylib but cannot compile the examples, check that
+# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations.
+# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED.
+# To enable compile-time linking to a special version of libraylib.so, change these variables here.
+# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below.
+# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime,
+# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH.
+# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths.
+DESTDIR ?= /usr/local
+RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib
+# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files.
+RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include
+
+# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
+RAYLIB_LIBTYPE        ?= STATIC
+
+# Build mode for project: DEBUG or RELEASE
+BUILD_MODE            ?= RELEASE
+
+# Use external GLFW library instead of rglfw module
+# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3
+USE_EXTERNAL_GLFW     ?= FALSE
+
+# Use Wayland display server protocol on Linux desktop
+# by default it uses X11 windowing system
+USE_WAYLAND_DISPLAY   ?= FALSE
+
+# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
+    # ifeq ($(UNAME),Msys) -> Windows
+    ifeq ($(OS),Windows_NT)
+        PLATFORM_OS=WINDOWS
+    else
+        UNAMEOS=$(shell uname)
+        ifeq ($(UNAMEOS),Linux)
+            PLATFORM_OS=LINUX
+        endif
+        ifeq ($(UNAMEOS),FreeBSD)
+            PLATFORM_OS=BSD
+        endif
+        ifeq ($(UNAMEOS),OpenBSD)
+            PLATFORM_OS=BSD
+        endif
+        ifeq ($(UNAMEOS),NetBSD)
+            PLATFORM_OS=BSD
+        endif
+        ifeq ($(UNAMEOS),DragonFly)
+            PLATFORM_OS=BSD
+        endif
+        ifeq ($(UNAMEOS),Darwin)
+            PLATFORM_OS=OSX
+        endif
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    UNAMEOS=$(shell uname)
+    ifeq ($(UNAMEOS),Linux)
+        PLATFORM_OS=LINUX
+    endif
+endif
+
+# RAYLIB_PATH adjustment for different platforms.
+# If using GNU make, we can get the full path to the top of the tree. Windows? BSD?
+# Required for ldconfig or other tools that do not perform path expansion.
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),LINUX)
+        RAYLIB_PREFIX ?= ..
+        RAYLIB_PATH    = $(realpath $(RAYLIB_PREFIX))
+    endif
+endif
+# Default path for raylib on Raspberry Pi, if installed in different path, update it!
+# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki.
+# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX.
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    RAYLIB_PATH       ?= /home/pi/raylib
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+    # Emscripten required variables
+    EMSDK_PATH          ?= C:/emsdk
+    EMSCRIPTEN_VERSION  ?= 1.38.32
+    CLANG_VERSION       = e$(EMSCRIPTEN_VERSION)_64bit
+    PYTHON_VERSION      = 2.7.13.1_64bit\python-2.7.13.amd64
+    NODE_VERSION        = 8.9.1_64bit
+    export PATH         = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH)
+    EMSCRIPTEN          = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION)
+endif
+
+# Define raylib release directory for compiled library.
+# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version
+RAYLIB_RELEASE_PATH 	?= $(RAYLIB_PATH)/src
+
+# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
+# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH
+# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux
+# without formal installation from ../src/Makefile. It aids portability and is useful if you have
+# multiple versions of raylib, have raylib installed to a non-standard location, or want to
+# bundle libraylib.so with your game. Change it to your liking.
+# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH,
+# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH,
+# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute.
+# To see which libraries a built example is linking to, ldd core/core_basic_window;
+# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing.
+EXAMPLE_RUNTIME_PATH   ?= $(RAYLIB_RELEASE_PATH)
+
+# Define default C compiler: gcc
+# NOTE: define g++ compiler if using C++
+CC = gcc
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),OSX)
+        # OSX default compiler
+        CC = clang
+    endif
+    ifeq ($(PLATFORM_OS),BSD)
+        # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
+        CC = clang
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
+        # Define RPI cross-compiler
+        #CC = armv6j-hardfloat-linux-gnueabi-gcc
+        CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+    # HTML5 emscripten compiler
+    # WARNING: To compile to HTML5, code must be redesigned
+    # to use emscripten.h and emscripten_set_main_loop()
+    CC = emcc
+endif
+
+# Define default make program: Mingw32-make
+MAKE = mingw32-make
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),LINUX)
+        MAKE = make
+    endif
+endif
+
+# Define compiler flags:
+#  -O1                  defines optimization level
+#  -g                   include debug information on compilation
+#  -s                   strip unnecessary data from build
+#  -Wall                turns on most, but not all, compiler warnings
+#  -std=c99             defines C language mode (standard C from 1999 revision)
+#  -std=gnu99           defines C language mode (GNU C from 1999 revision)
+#  -Wno-missing-braces  ignore invalid warning (GCC bug 53119)
+#  -D_DEFAULT_SOURCE    use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
+CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces
+
+ifeq ($(BUILD_MODE),DEBUG)
+    CFLAGS += -g
+endif
+ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
+    CFLAGS += -O1 -s
+endif
+
+# Additional flags for compiler (if desired)
+#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),WINDOWS)
+        # resource file contains windows executable icon and properties
+        # -Wl,--subsystem,windows hides the console window
+        CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        ifeq ($(RAYLIB_LIBTYPE),STATIC)
+            CFLAGS += -D_DEFAULT_SOURCE
+        endif
+        ifeq ($(RAYLIB_LIBTYPE),SHARED)
+            # Explicitly enable runtime link to libraylib.so
+            CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+        endif
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    CFLAGS += -std=gnu99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+    # -Os                        # size optimization
+    # -O2                        # optimization level 2, if used, also set --memory-init-file 0
+    # -s USE_GLFW=3              # Use glfw3 library (context/input management)
+    # -s ALLOW_MEMORY_GROWTH=1   # to allow memory resizing -> WARNING: Audio buffers could FAIL!
+    # -s TOTAL_MEMORY=16777216   # to specify heap memory size (default = 16MB)
+    # -s USE_PTHREADS=1          # multithreading support
+    # -s WASM=0                  # disable Web Assembly, emitted by default
+    # -s EMTERPRETIFY=1          # enable emscripten code interpreter (very slow)
+    # -s EMTERPRETIFY_ASYNC=1    # support synchronous loops by emterpreter
+    # -s FORCE_FILESYSTEM=1      # force filesystem to load/save files data
+    # -s ASSERTIONS=1            # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
+    # --profiling                # include information for code profiling
+    # --memory-init-file 0       # to avoid an external memory initialization code file (.mem)
+    # --preload-file resources   # specify a resources folder for data compilation
+    CFLAGS += -Os -s USE_GLFW=3 -s FORCE_FILESYSTEM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 --preload-file $(dir $<)resources@resources
+    ifeq ($(BUILD_MODE), DEBUG)
+        CFLAGS += -s ASSERTIONS=1 --profiling
+    endif
+    # NOTE: Simple raylib examples are compiled to be interpreter by emterpreter, that way,
+    # we can compile same code for ALL platforms with no change required, but, working on bigger
+    # projects, code needs to be refactored to avoid a blocking while() loop, moving Update and Draw
+    # logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference.
+
+    # Define a custom shell .html and output extension
+    CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
+    EXT = .html
+endif
+
+# Define include paths for required headers
+# NOTE: Several external required libraries (stb and others)
+INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external -I$(RAYGUI_PATH)
+
+# Define additional directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    # RPI required libraries
+    INCLUDE_PATHS += -I/opt/vc/include
+    INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux
+    INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),BSD)
+        # Consider -L$(RAYLIB_H_INSTALL_PATH)
+        INCLUDE_PATHS += -I/usr/local/include
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        # Reset everything.
+        # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include
+        INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external
+    endif
+endif
+
+# Define library paths containing required libs.
+LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),BSD)
+        # Consider -L$(RAYLIB_INSTALL_PATH)
+        LDFLAGS += -L. -Lsrc -L/usr/local/lib
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        # Reset everything.
+        # Precedence: immediately local, installed version, raysan5 provided libs
+        LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH)
+    endif
+endif
+
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LDFLAGS += -L/opt/vc/lib
+endif
+
+# Define any libraries required on linking
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),WINDOWS)
+        # Libraries for Windows desktop compilation
+        # NOTE: WinMM library required to set high-res timer resolution
+        LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
+        # Required for physac examples
+        LDLIBS += -static -lpthread
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        # Libraries for Debian GNU/Linux desktop compiling
+        # NOTE: Required packages: libegl1-mesa-dev
+        LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
+
+        # On X11 requires also below libraries
+        LDLIBS += -lX11
+        # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
+        #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+
+        # On Wayland windowing system, additional libraries requires
+        ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
+            LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
+        endif
+        # Explicit link to libc
+        ifeq ($(RAYLIB_LIBTYPE),SHARED)
+            LDLIBS += -lc
+        endif
+    endif
+    ifeq ($(PLATFORM_OS),OSX)
+        # Libraries for OSX 10.9 desktop compiling
+        # NOTE: Required packages: libopenal-dev libegl1-mesa-dev
+        LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa
+    endif
+    ifeq ($(PLATFORM_OS),BSD)
+        # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
+        # NOTE: Required packages: mesa-libs
+        LDLIBS = -lraylib -lGL -lpthread -lm
+
+        # On XWindow requires also below libraries
+        LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+    endif
+    ifeq ($(USE_EXTERNAL_GLFW),TRUE)
+        # NOTE: It could require additional packages installed: libglfw3-dev
+        LDLIBS += -lglfw
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    # Libraries for Raspberry Pi compiling
+    # NOTE: Required packages: libasound2-dev (ALSA)
+    LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+    # Libraries for web (HTML5) compiling
+    LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc
+endif
+
+# Define all source files required
+EXAMPLES = \
+    controls_test_suite/controls_test_suite \
+    custom_file_dialog/custom_file_dialog \
+    image_exporter/image_exporter \
+    image_raw_importer/image_raw_importer \
+    portable_window/portable_window \
+    scroll_panel/gui_scroll_panel \
+    text_box_selection/gui_text_box
+
+CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
+
+# Default target entry
+all: $(EXAMPLES)
+
+# Generic compilation pattern
+# NOTE: Examples must be ready for Android compilation!
+%: %.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
+# Clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    ifeq ($(PLATFORM_OS),WINDOWS)
+		del *.o *.exe /s
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+	find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
+    endif
+    ifeq ($(PLATFORM_OS),OSX)
+		find . -type f -perm +ugo+x -delete
+		rm -f *.o
+    endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+	find . -type f -executable -delete
+	rm -fv *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+	del *.o *.html *.js
+endif
+	@echo Cleaning done

+ 245 - 0
gui.mod/raygui/examples/controls_test_suite/controls_test_suite.c

@@ -0,0 +1,245 @@
+/*******************************************************************************************
+*
+*   raygui - controls test suite
+*
+*   TEST CONTROLS:
+*       - GuiDropdownBox()
+*       - GuiCheckBox()
+*       - GuiSpinner()
+*       - GuiValueBox()
+*       - GuiTextBox()
+*       - GuiButton()
+*       - GuiComboBox()
+*       - GuiListView()
+*       - GuiToggleGroup()
+*       - GuiTextBoxMulti()
+*       - GuiColorPicker()
+*       - GuiSlider()
+*       - GuiSliderBar()
+*       - GuiProgressBar()
+*       - GuiColorBarAlpha()
+*       - GuiScrollPanel()
+*
+*
+*   DEPENDENCIES:
+*       raylib 2.6-dev  - Windowing/input management and drawing.
+*       raygui 2.6-dev  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_ICONS
+#include "../../src/raygui.h"
+
+#undef RAYGUI_IMPLEMENTATION            // Avoid including raygui implementation again
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    int screenWidth = 690;
+    int screenHeight = 560;
+    
+    InitWindow(screenWidth, screenHeight, "raygui - controls test suite");
+    SetExitKey(0);
+
+    // GUI controls initialization
+    //----------------------------------------------------------------------------------
+    int dropdownBox000Active = 0;
+    bool dropDown000EditMode = false;
+    
+    int dropdownBox001Active = 0;
+    bool dropDown001EditMode = false;    
+    
+    int spinner001Value = 0;
+    bool spinnerEditMode = false;
+    
+    int valueBox002Value = 0;
+    bool valueBoxEditMode = false;
+    
+    char textBoxText[64] = "Text box";
+    bool textBoxEditMode = false;
+    
+    int listViewScrollIndex = 0;
+    int listViewActive = -1;
+
+    int listViewExScrollIndex = 0;
+    int listViewExActive = 2;
+    int listViewExFocus = -1;
+    const char *listViewExList[8] = { "This", "is", "a", "list view", "with", "disable", "elements", "amazing!" };
+
+    char multiTextBoxText[141] = "Multi text box";    
+    bool multiTextBoxEditMode = false;
+    Color colorPickerValue = RED;
+    
+    int sliderValue = 50;
+    int sliderBarValue = 60;
+    float progressValue = 0.4f;
+    
+    bool forceSquaredChecked = false;
+    
+    float alphaValue = 0.5f;
+    
+    int comboBoxActive = 1;
+    
+    int toggleGroupActive = 0;
+    
+    Vector2 viewScroll = { 0, 0 };
+    //----------------------------------------------------------------------------------
+
+    // Custom GUI font loading
+    //Font font = LoadFontEx("fonts/rainyhearts16.ttf", 12, 0, 0);
+    //GuiSetFont(font);
+    
+    bool exitWindow = false;
+    bool showMessageBox = false;
+    
+    char textInput[256] = { 0 };
+    bool showTextInputBox = false;
+    
+    char textInputFileName[256] = { 0 };
+
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!exitWindow)    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        exitWindow = WindowShouldClose();
+        
+        if (IsKeyPressed(KEY_ESCAPE)) showMessageBox = !showMessageBox;
+        
+        if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_S)) showTextInputBox = true;
+        
+        if (IsFileDropped())
+        {
+            int dropsCount = 0;
+            char **droppedFiles = GetDroppedFiles(&dropsCount);
+            
+            if ((dropsCount > 0) && IsFileExtension(droppedFiles[0], ".rgs")) GuiLoadStyle(droppedFiles[0]);
+            
+            ClearDroppedFiles();    // Clear internal buffers
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+ 
+            // raygui: controls drawing
+            //----------------------------------------------------------------------------------
+            if (dropDown000EditMode || dropDown001EditMode) GuiLock();
+            //GuiDisable();
+            
+            // First GUI column
+            //GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+            forceSquaredChecked = GuiCheckBox((Rectangle){ 25, 108, 15, 15 }, "FORCE CHECK!", forceSquaredChecked);
+            
+            GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+            //GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+            if (GuiSpinner((Rectangle){ 25, 135, 125, 30 }, NULL, &spinner001Value, 0, 100, spinnerEditMode)) spinnerEditMode = !spinnerEditMode;
+            if (GuiValueBox((Rectangle){ 25, 175, 125, 30 }, NULL, &valueBox002Value, 0, 100, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode;
+            GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+            if (GuiTextBox((Rectangle){ 25, 215, 125, 30 }, textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
+            
+            GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+            
+            if (GuiButton((Rectangle){ 25, 255, 125, 30 }, GuiIconText(RICON_FILE_SAVE, "Save File"))) showTextInputBox = true;
+            
+            GuiGroupBox((Rectangle){ 25, 310, 125, 150 }, "STATES");
+            GuiLock();
+            GuiSetState(GUI_STATE_NORMAL); if (GuiButton((Rectangle){ 30, 320, 115, 30 }, "NORMAL")) { }
+            GuiSetState(GUI_STATE_FOCUSED); if (GuiButton((Rectangle){ 30, 355, 115, 30 }, "FOCUSED")) { }
+            GuiSetState(GUI_STATE_PRESSED); if (GuiButton((Rectangle){ 30, 390, 115, 30 }, "#15#PRESSED")) { }
+            GuiSetState(GUI_STATE_DISABLED); if (GuiButton((Rectangle){ 30, 425, 115, 30 }, "DISABLED")) { }
+            GuiSetState(GUI_STATE_NORMAL);
+            GuiUnlock();
+            
+            comboBoxActive = GuiComboBox((Rectangle){ 25, 470, 125, 30 }, "ONE;TWO;THREE;FOUR", comboBoxActive);
+            
+            // NOTE: GuiDropdownBox must draw after any other control that can be covered on unfolding
+            GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+            if (GuiDropdownBox((Rectangle){ 25, 65, 125, 30 }, "#01#ONE;#02#TWO;#03#THREE;#04#FOUR", &dropdownBox001Active, dropDown001EditMode)) dropDown001EditMode = !dropDown001EditMode;
+
+            GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+            if (GuiDropdownBox((Rectangle){ 25, 25, 125, 30 }, "ONE;TWO;THREE", &dropdownBox000Active, dropDown000EditMode)) dropDown000EditMode = !dropDown000EditMode;
+
+            // Second GUI column
+            listViewActive = GuiListView((Rectangle){ 165, 25, 140, 140 }, "Charmander;Bulbasaur;#18#Squirtel;Pikachu;Eevee;Pidgey", &listViewScrollIndex, listViewActive);
+            listViewExActive = GuiListViewEx((Rectangle){ 165, 180, 140, 200 }, listViewExList, 8, &listViewExFocus, &listViewExScrollIndex, listViewExActive);
+
+            toggleGroupActive = GuiToggleGroup((Rectangle){ 165, 400, 140, 25 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", toggleGroupActive);
+            
+            // Third GUI column
+            if (GuiTextBoxMulti((Rectangle){ 320, 25, 225, 140 }, multiTextBoxText, 141, multiTextBoxEditMode)) multiTextBoxEditMode = !multiTextBoxEditMode;
+            colorPickerValue = GuiColorPicker((Rectangle){ 320, 185, 196, 192 }, colorPickerValue);
+            
+            sliderValue = GuiSlider((Rectangle){ 355, 400, 165, 20 }, "TEST", TextFormat("%2.2f", (float)sliderValue), sliderValue, -50, 100);
+            sliderBarValue = GuiSliderBar((Rectangle){ 320, 430, 200, 20 }, NULL, TextFormat("%i", (int)sliderBarValue), sliderBarValue, 0, 100);
+            progressValue = GuiProgressBar((Rectangle){ 320, 460, 200, 20 }, NULL, NULL, progressValue, 0, 1);
+
+            // NOTE: View rectangle could be used to perform some scissor test
+            Rectangle view = GuiScrollPanel((Rectangle){ 560, 25, 100, 160 }, (Rectangle){ 560, 25, 200, 400 }, &viewScroll);
+            
+            GuiStatusBar((Rectangle){ 0, GetScreenHeight() - 20, GetScreenWidth(), 20 }, "This is a status bar");
+            
+            alphaValue = GuiColorBarAlpha((Rectangle){ 320, 490, 200, 30 }, alphaValue);
+
+            if (showMessageBox)
+            {
+                DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f));
+                int result = GuiMessageBox((Rectangle){ GetScreenWidth()/2 - 125, GetScreenHeight()/2 - 50, 250, 100 }, GuiIconText(RICON_EXIT, "Close Window"), "Do you really want to exit?", "Yes;No"); 
+            
+                if ((result == 0) || (result == 2)) showMessageBox = false;
+                else if (result == 1) exitWindow = true;
+            }
+            
+            if (showTextInputBox)
+            {
+                DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f));
+                int result = GuiTextInputBox((Rectangle){ GetScreenWidth()/2 - 120, GetScreenHeight()/2 - 60, 240, 140 }, GuiIconText(RICON_FILE_SAVE, "Save file as..."), "Introduce a save file name", "Ok;Cancel", textInput);
+                
+                if (result == 1)
+                {
+                    // TODO: Validate textInput value and save
+                    
+                    strcpy(textInputFileName, textInput);
+                }
+                
+                if ((result == 0) || (result == 1) || (result == 2)) 
+                {
+                    showTextInputBox = false;
+                    strcpy(textInput, "\0");
+                }
+            }
+            
+            GuiUnlock();
+            //----------------------------------------------------------------------------------
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

二进制
gui.mod/raygui/examples/controls_test_suite/fonts/FiveByFive10.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/NorthernLights.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/PIXEARG11.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/PixelOperator8.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/pixelpoiiz10.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/prstartk8.ttf


二进制
gui.mod/raygui/examples/controls_test_suite/fonts/rainyhearts16.ttf


二进制
gui.mod/raygui/examples/custom_file_dialog/cat.png


+ 113 - 0
gui.mod/raygui/examples/custom_file_dialog/custom_file_dialog.c

@@ -0,0 +1,113 @@
+/*******************************************************************************************
+*
+*   raygui - custom file dialog to load image
+*
+*   DEPENDENCIES:
+*       raylib 2.6-dev  - Windowing/input management and drawing.
+*       raygui 2.6-dev  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_ICONS
+#include "../../src/raygui.h"
+
+#undef RAYGUI_IMPLEMENTATION            // Avoid including raygui implementation again
+
+#define GUI_FILE_DIALOG_IMPLEMENTATION
+#include "gui_file_dialog.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    int screenWidth = 800;
+    int screenHeight = 560;
+    
+    InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
+    SetExitKey(0);
+
+    // Custom file dialog
+    GuiFileDialogState fileDialogState = InitGuiFileDialog();
+
+    bool exitWindow = false;
+
+    char fileNameToLoad[512] = { 0 };
+    
+    Texture texture = { 0 };
+
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!exitWindow)    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        exitWindow = WindowShouldClose();
+        
+        if (fileDialogState.SelectFilePressed)
+        {
+            // Load image file (if supported extension)
+            if (IsFileExtension(fileDialogState.fileNameText, ".png"))
+            {
+                strcpy(fileNameToLoad, TextFormat("%s/%s", fileDialogState.dirPathText, fileDialogState.fileNameText));
+                UnloadTexture(texture);
+                texture = LoadTexture(fileNameToLoad);
+            }
+            
+            fileDialogState.SelectFilePressed = false;
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+            
+            DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE);
+            DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK);
+ 
+            DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
+ 
+            // raygui: controls drawing
+            //----------------------------------------------------------------------------------
+            if (fileDialogState.fileDialogActive) GuiLock();
+
+            if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true;
+            
+            GuiUnlock();
+            
+            // GUI: Dialog Window
+            //--------------------------------------------------------------------------------
+            GuiFileDialog(&fileDialogState);
+            //--------------------------------------------------------------------------------
+
+            //----------------------------------------------------------------------------------
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadTexture(texture);     // Unload texture
+
+    CloseWindow();              // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 558 - 0
gui.mod/raygui/examples/custom_file_dialog/gui_file_dialog.h

@@ -0,0 +1,558 @@
+/*******************************************************************************************
+*
+*   FileDialog v1.0.0 - Modal file dialog to open/save files
+*
+*   MODULE USAGE:
+*       #define GUI_FILE_DIALOG_IMPLEMENTATION
+*       #include "gui_file_dialog.h"
+*
+*       INIT: GuiFileDialogState state = InitGuiFileDialog();
+*       DRAW: GuiFileDialog(&state);
+*
+*   NOTE: This module depends on some raylib file system functions:
+*       - GetDirectoryFiles()
+*       - ClearDirectoryFiles()
+*       - GetWorkingDirectory()
+*       - DirectoryExists()
+*       - FileExists()
+*
+*   LICENSE: Propietary License
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech). All Rights Reserved.
+*
+*   Unauthorized copying of this file, via any medium is strictly prohibited
+*   This project is proprietary and confidential unless the owner allows
+*   usage in any other form by expresely written permission.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+// WARNING: raygui implementation is expected to be defined before including this header
+#undef RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+#ifndef GUI_FILE_DIALOG_H
+#define GUI_FILE_DIALOG_H
+
+typedef struct {
+    Vector2 position;
+    
+    bool fileDialogActive;
+    
+    bool dirPathEditMode;
+    char dirPathText[256];
+    
+    int filesListScrollIndex;
+    bool filesListEditMode;
+    int filesListActive;
+    
+    bool fileNameEditMode;
+    char fileNameText[256];
+    bool SelectFilePressed;
+    bool CancelFilePressed;
+    int fileTypeActive;
+
+    // Custom state variables (depend on development software)
+    // NOTE: This variables should be added manually if required
+    char **dirFiles;
+    int dirFilesCount;
+
+    char filterExt[256];
+    
+    char dirPathTextCopy[256];
+    char fileNameTextCopy[256];
+    
+    int prevFilesListActive;
+
+} GuiFileDialogState;
+
+#ifdef __cplusplus
+extern "C" {            // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+GuiFileDialogState InitGuiFileDialog(void);
+void GuiFileDialog(GuiFileDialogState *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUI_FILE_DIALOG_H
+
+/***********************************************************************************
+*
+*   GUI_FILE_DIALOG IMPLEMENTATION
+*
+************************************************************************************/
+#if defined(GUI_FILE_DIALOG_IMPLEMENTATION)
+
+#include "../../src/raygui.h"
+
+#include <string.h>     // Required for: strcpy()
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define MAX_DIRECTORY_FILES    1024
+#define MAX_DIR_PATH_LENGTH    1024
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// Detailed file info type
+typedef struct FileInfo {
+    const char *name;
+    int size;
+    int modTime;
+    int type;
+    int icon;
+} FileInfo;
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+char **dirFilesIcon = NULL;
+
+//----------------------------------------------------------------------------------
+// Internal Module Functions Definition
+//----------------------------------------------------------------------------------
+// Read all filenames from directory (supported file types)
+static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt);
+
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// List View control for files info with extended parameters
+static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active)
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+GuiFileDialogState InitGuiFileDialog(void)
+{
+    GuiFileDialogState state = { 0 };
+
+    state.position = (Vector2){ GetScreenWidth()/2 - 480/2, GetScreenHeight()/2 - 305/2 };
+    
+    state.fileDialogActive = false;
+    state.dirPathEditMode = false;
+    
+    state.filesListActive = -1;
+    state.prevFilesListActive = state.filesListActive;
+    state.filesListScrollIndex = 0;
+    
+    state.fileNameEditMode = false;
+
+    state.SelectFilePressed = false;
+    state.CancelFilePressed = false;
+
+    state.fileTypeActive = 0;
+
+    // Custom variables initialization
+    strcpy(state.dirPathText, GetWorkingDirectory());
+    strcpy(state.dirPathTextCopy, state.dirPathText);
+    
+    strcpy(state.filterExt, "all");
+
+    state.dirFilesCount = 0;
+    state.dirFiles = NULL;      // NOTE: Loaded lazily on window active
+    
+    strcpy(state.fileNameText, "\0");
+    strcpy(state.fileNameTextCopy, state.fileNameText);
+
+    return state;
+}
+
+void GuiFileDialog(GuiFileDialogState *state)
+{   
+    if (state->fileDialogActive)
+    {
+        // Load dirFilesIcon and state->dirFiles lazily on windows open
+        // NOTE: they are automatically unloaded at fileDialog closing
+        //------------------------------------------------------------------------------------
+        if (dirFilesIcon == NULL)
+        {
+            dirFilesIcon = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *));    // Max files to read
+            for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)calloc(MAX_DIR_PATH_LENGTH, 1);    // Max file name length
+        }
+    
+        if (state->dirFiles == NULL) state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
+        //------------------------------------------------------------------------------------
+
+        DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.85f));
+        state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, 480, 310 }, "#198#Select File Dialog");
+        
+        if (GuiButton((Rectangle){ state->position.x + 430, state->position.y + 35, 40, 25 }, "< .."))
+        {
+            // Move dir path one level up
+            strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
+            
+            // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
+            for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
+            RL_FREE(state->dirFiles);
+            
+            // Read files in the new path
+            state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
+            
+            state->filesListActive = -1;
+            strcpy(state->fileNameText, "\0");
+            strcpy(state->fileNameTextCopy, state->fileNameText);
+        }
+        
+        if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, 410, 25 }, state->dirPathText, 256, state->dirPathEditMode)) 
+        {
+            if (state->dirPathEditMode)
+            {
+                // Verify if a valid path has been introduced
+                if (DirectoryExists(state->dirPathText))
+                {
+                    // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
+                    for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
+                    RL_FREE(state->dirFiles);
+                    
+                    // Read files in new path
+                    state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
+                    
+                    strcpy(state->dirPathTextCopy, state->dirPathText);
+                }
+                else strcpy(state->dirPathText, state->dirPathTextCopy);
+            }
+            
+            state->dirPathEditMode = !state->dirPathEditMode;
+        }
+        
+        int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
+        int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+        GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+        GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
+        
+        // TODO: ListViewElements should be aligned left
+        state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, 460, 164 }, (const char **)dirFilesIcon, state->dirFilesCount, NULL, &state->filesListScrollIndex, state->filesListActive);
+        
+        GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
+        GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
+        
+        if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
+        {
+            strcpy(state->fileNameText, state->dirFiles[state->filesListActive]);
+
+            if (DirectoryExists(TextFormat("%s\\%s", state->dirPathText, state->fileNameText)))
+            {
+                if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
+                else strcpy(state->dirPathText, TextFormat("%s\\%s", state->dirPathText, state->fileNameText));
+                
+                strcpy(state->dirPathTextCopy, state->dirPathText);
+                
+                // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
+                for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
+                RL_FREE(state->dirFiles);
+                
+                // Read files in new path
+                state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
+                
+                strcpy(state->dirPathTextCopy, state->dirPathText);
+                
+                state->filesListActive = -1;
+                strcpy(state->fileNameText, "\0");
+                strcpy(state->fileNameTextCopy, state->fileNameText);
+            }
+
+            state->prevFilesListActive = state->filesListActive;
+        }
+        
+        GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 245, 68, 25 }, "File name:");
+        
+        if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + 245, 275, 25 }, state->fileNameText, 128, state->fileNameEditMode)) 
+        {
+            if (state->fileNameText)
+            {
+                // Verify if a valid filename has been introduced
+                if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
+                {
+                    // Select filename from list view
+                    for (int i = 0; i < state->dirFilesCount; i++)
+                    {
+                        if (TextIsEqual(state->fileNameText, state->dirFiles[i]))
+                        {
+                            state->filesListActive = i;
+                            strcpy(state->fileNameTextCopy, state->fileNameText);
+                            break;
+                        }
+                    }
+                }
+                else 
+                {
+                    strcpy(state->fileNameText, state->fileNameTextCopy);
+                }
+            }
+            
+            state->fileNameEditMode = !state->fileNameEditMode;
+        }
+
+        state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + 275, 275, 25 }, "All files", state->fileTypeActive);
+        GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 275, 68, 25 }, "File filter:");
+        
+        state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + 360, state->position.y + 245, 110, 25 }, "Select");
+        
+        if (state->SelectFilePressed) state->fileDialogActive = false;
+        
+        if (GuiButton((Rectangle){ state->position.x + 360, state->position.y + 275, 110, 25 }, "Cancel")) state->fileDialogActive = false;
+
+        // File dialog has been closed!
+        if (!state->fileDialogActive)
+        {
+            // RL_FREE dirFiles memory
+            for (int i = 0; i < state->dirFilesCount; i++) 
+            {
+                RL_FREE(state->dirFiles[i]);
+                RL_FREE(dirFilesIcon[i]);
+            }
+            
+            RL_FREE(state->dirFiles);
+            RL_FREE(dirFilesIcon);
+            
+            dirFilesIcon = NULL;
+            state->dirFiles = NULL;
+        }
+    }
+}
+
+// Read all filenames from directory (supported file types)
+static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt)
+{
+    int validFilesCount = 0;
+    char **validFiles = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *));    // Max files to read
+    for (int i = 0; i < MAX_DIRECTORY_FILES; i++) validFiles[i] = (char *)RL_MALLOC(MAX_DIR_PATH_LENGTH);    // Max file name length
+    
+    int filterExtCount = 0;
+    const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL);
+    bool filterExtensions = true;
+    
+    int dirFilesCount = 0;
+    char **files = GetDirectoryFiles(dir, &dirFilesCount);
+    
+    if (TextIsEqual(extensions[0], "all")) filterExtensions = false;
+
+    for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++)
+    {
+        if (TextIsEqual(files[i], ".")) continue;
+        
+        if (!filterExtensions)
+        {
+            strcpy(validFiles[validFilesCount], files[i]);
+            
+            // Only filter files by extensions, directories should be available
+            if (DirectoryExists(TextFormat("%s\\%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
+            else 
+            {
+                // TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...)
+                
+                if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
+                else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
+            }
+
+            validFilesCount++;
+        }
+        else
+        {
+            for (int j = 0; j < filterExtCount; j++)
+            {
+                // Check file type extensions supported
+                // NOTE: We just store valid files list
+                if (IsFileExtension(files[i], extensions[j]))
+                {
+                    // TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...)
+
+                    if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
+                    else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
+                    
+                    validFilesCount++;
+                }
+            }
+        }
+    }
+    
+    // TODO: Sort files and directories: dir by name + files by name
+
+    ClearDirectoryFiles();
+    
+    *filesCount = validFilesCount;
+    return validFiles;
+}
+
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// List View control for files info with extended parameters
+static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active)
+{
+    GuiControlState state = guiState;
+    int itemFocused = (focus == NULL)? -1 : *focus;
+    int itemSelected = active;
+    
+    // Check if we need a scroll bar
+    bool useScrollBar = false;
+    if ((GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING))*count > bounds.height) useScrollBar = true;
+    
+    // Define base item rectangle [0]
+    Rectangle itemBounds = { 0 };
+    itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING);
+    itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    itemBounds.height = GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT);
+    if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+    
+    // Get items on the list
+    int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
+    if (visibleItems > count) visibleItems = count;
+    
+    int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
+    if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
+    int endIndex = startIndex + visibleItems;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+        
+        // Check mouse inside list view
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            state = GUI_STATE_FOCUSED;
+            
+            // Check focused and selected item
+            for (int i = 0; i < visibleItems; i++)
+            {
+                if (CheckCollisionPointRec(mousePoint, itemBounds))
+                {
+                    itemFocused = startIndex + i;
+                    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
+                    break;
+                }
+                
+                // Update item rectangle y position for next item
+                itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
+            }
+            
+            if (useScrollBar)
+            {
+                int wheelMove = GetMouseWheelMove();
+                startIndex -= wheelMove;
+                    
+                if (startIndex < 0) startIndex = 0;
+                else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
+
+                endIndex = startIndex + visibleItems;
+                if (endIndex > count) endIndex = count;
+            }
+        }
+        else itemFocused = -1;
+        
+        // Reset item rectangle y to [0]
+        itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    }
+    //--------------------------------------------------------------------
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));     // Draw background
+    DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
+
+    // TODO: Draw list view header with file sections: icon+name | size | type | modTime
+    
+    // Draw visible items
+    for (int i = 0; i < visibleItems; i++)
+    {
+        if (state == GUI_STATE_DISABLED)
+        {
+            if ((startIndex + i) == itemSelected)
+            {
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha));
+            }
+            
+            // TODO: Draw full file info line: icon+name | size | type | modTime 
+            
+            GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
+        }
+        else
+        {
+            if ((startIndex + i) == itemSelected)
+            {
+                // Draw item selected
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha));
+                
+                GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
+            }
+            else if ((startIndex + i) == itemFocused)
+            {
+                // Draw item focused
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha));
+                
+                GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
+            }
+            else
+            {
+                // Draw item normal
+                GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
+            }
+        }
+
+        // Update item rectangle y position for next item
+        itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
+    }
+
+    if (useScrollBar)
+    {
+        Rectangle scrollBarBounds = { 
+            bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), 
+            bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), 
+            bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) 
+        };
+
+        // Calculate percentage of visible items and apply same percentage to scrollbar
+        float percentVisible = (float)(endIndex - startIndex)/count;
+        float sliderSize = bounds.height*percentVisible;
+
+        int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_SIZE);   // Save default slider size
+        int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
+        GuiSetStyle(SCROLLBAR, SLIDER_SIZE, sliderSize);            // Change slider size
+        GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
+
+        startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
+
+        GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
+        GuiSetStyle(SCROLLBAR, SLIDER_SIZE, prevSliderSize); // Reset slider size to default
+    }
+    //--------------------------------------------------------------------
+    
+    if (focus != NULL) *focus = itemFocused;
+    if (scrollIndex != NULL) *scrollIndex = startIndex;
+    
+    return itemSelected;
+}
+#endif // USE_CUSTOM_LISTVIEW_FILEINFO
+
+#endif // GUI_FILE_DIALOG_IMPLEMENTATION

+ 195 - 0
gui.mod/raygui/examples/image_exporter/image_exporter.c

@@ -0,0 +1,195 @@
+/*******************************************************************************************
+*
+*   raygui - image exporter
+*
+*   DEPENDENCIES:
+*       raylib 2.1  - Windowing/input management and drawing.
+*       raygui 2.0  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_RICONS
+#include "../../src/raygui.h"
+
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(int argc, char *argv[0])
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+    
+    InitWindow(screenWidth, screenHeight, "raygui - image exporter");
+    
+    // GUI controls initialization
+    //----------------------------------------------------------------------------------
+    Rectangle windowBoxRec = { screenWidth/2 - 110, screenHeight/2 - 100, 220, 190 };
+    bool windowBoxActive = false;
+    
+    int fileFormatActive = 0;
+    const char *fileFormatTextList[3] = { "IMAGE (.png)", "DATA (.raw)", "CODE (.h)" };
+
+    int pixelFormatActive = 0;
+    const char *pixelFormatTextList[7] = { "GRAYSCALE", "GRAY ALPHA", "R5G6B5", "R8G8B8", "R5G5B5A1", "R4G4B4A4", "R8G8B8A8" };
+
+    bool textBoxEditMode = false;
+    char fileName[32] = "untitled";
+    //--------------------------------------------------------------------------------------
+    
+    Image image = { 0 };
+    Texture2D texture = { 0 };
+    
+    bool imageLoaded = false;
+    float imageScale = 1.0f;
+    Rectangle imageRec = { 0.0f };
+    
+    bool btnExport = false;
+
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        if (IsFileDropped())
+        {
+            int fileCount = 0;
+            char **droppedFiles = GetDroppedFiles(&fileCount);
+
+            if (fileCount == 1)
+            {
+                Image imTemp = LoadImage(droppedFiles[0]);
+                
+                if (imTemp.data != NULL)
+                {
+                    UnloadImage(image);
+                    image = imTemp;
+                    
+                    UnloadTexture(texture);
+                    texture = LoadTextureFromImage(image);
+                    
+                    imageLoaded = true;
+                    pixelFormatActive = image.format - 1;
+                    
+                    if (texture.height > texture.width) imageScale = (float)(screenHeight - 100)/(float)texture.height;
+                    else imageScale = (float)(screenWidth - 100)/(float)texture.width;
+                }
+            }
+
+            ClearDroppedFiles();
+        }
+    
+        if (btnExport)
+        {
+            if (imageLoaded)
+            {
+                ImageFormat(&image, pixelFormatActive + 1);
+                
+                if (fileFormatActive == 0)        // PNG
+                {
+                    if ((GetExtension(fileName) == NULL) || (!IsFileExtension(fileName, ".png"))) strcat(fileName, ".png\0");     // No extension provided
+                    ExportImage(image, fileName);
+                }
+                else if (fileFormatActive == 1)   // RAW
+                {
+                    if ((GetExtension(fileName) == NULL) || (!IsFileExtension(fileName, ".raw"))) strcat(fileName, ".raw\0");     // No extension provided
+                    
+                    int dataSize = GetPixelDataSize(image.width, image.height, image.format);
+                    
+                    FILE *rawFile = fopen(fileName, "wb");  
+                    fwrite(image.data, dataSize, 1, rawFile);
+                    fclose(rawFile);
+                }
+                else if (fileFormatActive == 2)   // CODE
+                {
+                    ExportImageAsCode(image, fileName);
+                }
+            }
+            
+            windowBoxActive = false;
+        }
+        
+        if (imageLoaded)
+        {
+            imageScale += (float)GetMouseWheelMove()*0.05f;   // Image scale control
+            if (imageScale <= 0.1f) imageScale = 0.1f;
+            else if (imageScale >= 5) imageScale = 5;
+            
+            imageRec = (Rectangle){ screenWidth/2 - (float)image.width*imageScale/2, 
+                                    screenHeight/2 - (float)image.height*imageScale/2, 
+                                    (float)image.width*imageScale, (float)image.height*imageScale };
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            if (texture.id > 0)
+            {
+                DrawTextureEx(texture, (Vector2){ screenWidth/2 - (float)texture.width*imageScale/2, screenHeight/2 - (float)texture.height*imageScale/2 }, 0.0f, imageScale, WHITE);
+                
+                DrawRectangleLinesEx(imageRec, 1, CheckCollisionPointRec(GetMousePosition(), imageRec) ? RED : DARKGRAY); 
+                DrawText(FormatText("SCALE: %.2f%%", imageScale*100.0f), 20, screenHeight - 40, 20, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+            }
+            else
+            {
+                DrawText("DRAG & DROP YOUR IMAGE!", 350, 200, 10, DARKGRAY);
+                GuiDisable();
+            }
+            
+            if (GuiButton((Rectangle){ screenWidth - 170, screenHeight - 50, 150, 30 }, "Image Export")) windowBoxActive = true;
+            GuiEnable();
+            
+            // Draw window box: windowBoxName
+            //-----------------------------------------------------------------------------
+            if (windowBoxActive)
+            {
+                DrawRectangle(0, 0, screenWidth, screenHeight, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.7f));
+                windowBoxActive = !GuiWindowBox((Rectangle){ windowBoxRec.x, windowBoxRec.y, 220, 190 }, "Image Export Options");
+            
+                GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 35, 60, 25 }, "File format:");
+                fileFormatActive = GuiComboBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 35, 130, 25 }, TextJoin(fileFormatTextList, 3, ";"), fileFormatActive); 
+                GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 70, 63, 25 }, "Pixel format:");
+                pixelFormatActive = GuiComboBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 70, 130, 25 }, TextJoin(pixelFormatTextList, 7, ";"), pixelFormatActive); 
+                GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 105, 50, 25 }, "File name:");
+                if (GuiTextBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 105, 130, 25 }, fileName, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
+
+                btnExport = GuiButton((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 145, 200, 30 }, "Export Image");
+            }
+            else btnExport = false;
+            
+            if (btnExport) DrawText("Image exported!", 20, screenHeight - 20, 20, RED);
+            //-----------------------------------------------------------------------------
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadImage(image);
+    UnloadTexture(texture);
+    
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

二进制
gui.mod/raygui/examples/image_exporter/resources/cat.png


二进制
gui.mod/raygui/examples/image_exporter/resources/fudesumi.png


二进制
gui.mod/raygui/examples/image_exporter/resources/parrots.png


二进制
gui.mod/raygui/examples/image_exporter/resources/scarfy.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REF.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV0.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV1.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV2.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV3.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV4.png


二进制
gui.mod/raygui/examples/image_raw_importer/design/raw_importer_REV5.png


二进制
gui.mod/raygui/examples/image_raw_importer/image_2x2_RGBA.raw


+ 230 - 0
gui.mod/raygui/examples/image_raw_importer/image_raw_importer.c

@@ -0,0 +1,230 @@
+/*******************************************************************************************
+*
+*   raygui - image raw importer
+*
+*   DEPENDENCIES:
+*       raylib 2.1  - Windowing/input management and drawing.
+*       raygui 2.0  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_RICONS
+#include "../../src/raygui.h"
+
+#include <string.h>             // Required for: strcpy()
+#include <stdlib.h>             // Required for: atoi()
+#include <math.h>               // Required for: round()
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 600;
+
+    InitWindow(screenWidth, screenHeight, "raygui - image raw importer");
+    
+    Texture2D texture = { 0 };
+
+    // GUI controls initialization
+    //----------------------------------------------------------------------------------
+    Vector2 windowOffset = { screenWidth/2 - 200/2, screenHeight/2 - 465/2 };
+
+    bool importWindowActive = false;
+    
+    int widthValue = 0;
+    bool widthEditMode = false;
+    int heightValue = 0;
+    bool heightEditMode = false;
+    
+    int pixelFormatActive = 0;
+    const char *pixelFormatTextList[8] = { "CUSTOM", "GRAYSCALE", "GRAY ALPHA", "R5G6B5", "R8G8B8", "R5G5B5A1", "R4G4B4A4", "R8G8B8A8" };
+
+    int channelsActive = 3;
+    const char *channelsTextList[4] = { "1", "2", "3", "4" };
+    int bitDepthActive = 0;
+    const char *bitDepthTextList[3] = { "8", "16", "32" };
+    
+    int headerSizeValue = 0;
+    bool headerSizeEditMode = false;
+    //----------------------------------------------------------------------------------
+    
+    // Image file info
+    int dataSize = 0;
+    char fileNamePath[256] = "\0";
+    char fileName[64] = "\0";
+    
+    bool btnLoadPressed = false;
+    
+    bool imageLoaded = false;
+    float imageScale = 1.0f;
+
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        // Check if a file is dropped
+        if (IsFileDropped())
+        {
+            int fileCount = 0;
+            char **droppedFiles = GetDroppedFiles(&fileCount);
+
+            // Check file extensions for drag-and-drop
+            if ((fileCount == 1) && IsFileExtension(droppedFiles[0], ".raw"))
+            {
+                FILE *imageFile = fopen(droppedFiles[0], "rb");
+                fseek(imageFile, 0L, SEEK_END);
+                dataSize = ftell(imageFile);
+                fclose(imageFile);
+                
+                // NOTE: Returned string is just a pointer to droppedFiles[0],
+                // we need to make a copy of that data somewhere else: fileName
+                strcpy(fileNamePath, droppedFiles[0]);
+                strcpy(fileName, GetFileName(droppedFiles[0]));
+                
+                // Try to guess possible raw values
+                // Let's assume image is square, RGBA, 8 bit per channel
+                widthValue = round(sqrt(dataSize/4));
+                heightValue = widthValue;
+                headerSizeValue = dataSize - widthValue*heightValue*4;
+                if (headerSizeValue < 0) headerSizeValue = 0;
+
+                importWindowActive = true;
+            }
+
+            ClearDroppedFiles();
+        }
+        
+        // Check if load button has been pressed
+        if (btnLoadPressed)
+        {
+            // Depending on channels and bit depth, select correct pixel format
+            if ((widthValue != 0) && (heightValue != 0))
+            {
+                int format = -1;
+
+                if (pixelFormatActive == 0)
+                {
+                    int channels = atoi(channelsTextList[channelsActive]);
+                    int bpp = atoi(bitDepthTextList[bitDepthActive]);
+            
+                    // Select correct format depending on channels and bpp
+                    if (bpp == 8)
+                    {
+                        if (channels == 1) format = UNCOMPRESSED_GRAYSCALE;
+                        else if (channels == 2) format = UNCOMPRESSED_GRAY_ALPHA;
+                        else if (channels == 3) format = UNCOMPRESSED_R8G8B8;
+                        else if (channels == 4) format = UNCOMPRESSED_R8G8B8A8;
+                    }
+                    else if (bpp == 32)
+                    {
+                        if (channels == 1) format = UNCOMPRESSED_R32;
+                        else if (channels == 2) TraceLog(LOG_WARNING, "Channel bit-depth not supported!");
+                        else if (channels == 3) format = UNCOMPRESSED_R32G32B32;
+                        else if (channels == 4) format = UNCOMPRESSED_R32G32B32A32;
+                    }
+                    else if (bpp == 16) TraceLog(LOG_WARNING, "Channel bit-depth not supported!");
+                }
+                else format = pixelFormatActive;
+                
+                if (format != -1)
+                {
+                    Image image = LoadImageRaw(fileNamePath, widthValue, heightValue, format, headerSizeValue);
+                    texture = LoadTextureFromImage(image);
+                    UnloadImage(image);
+                    
+                    importWindowActive = false;
+                    btnLoadPressed = false;
+                    
+                    if (texture.id > 0)
+                    {
+                        imageLoaded = true;
+                        imageScale = (float)(screenHeight - 100)/texture.height;
+                    }
+                }
+            }
+        }
+        
+        if (imageLoaded) imageScale += (float)GetMouseWheelMove();   // Image scale control
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+            
+            if (texture.id != 0) 
+            {
+                DrawTextureEx(texture, (Vector2){ screenWidth/2 - texture.width*imageScale/2, screenHeight/2 - texture.height*imageScale/2 }, 0, imageScale, WHITE);
+                DrawText(FormatText("SCALE x%.0f", imageScale), 20, screenHeight - 40, 20, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+            }
+            else DrawText("drag & drop RAW image file", 320, 180, 10, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+
+            // raygui: controls drawing
+            //----------------------------------------------------------------------------------
+            if (importWindowActive)
+            {
+                importWindowActive = !GuiWindowBox((Rectangle){ windowOffset.x + 0, windowOffset.y + 0, 200, 465 }, "Image RAW Import Options");
+            
+                GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 30, 65, 20 }, "Import file:");
+                GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 30, 75, 20 }, fileName);
+                GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 50, 65, 20 }, "File size:");
+                GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 50, 75, 20 }, FormatText("%i bytes", dataSize));
+                GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 85, 180, 80 }, "Resolution");
+                GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 100, 33, 25 }, "Width:");
+                if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 100, 80, 25 }, NULL, &widthValue, 0, 8192, widthEditMode)) widthEditMode = !widthEditMode; 
+                GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 100, 30, 25 }, "pixels");
+                GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 130, 33, 25 }, "Height:");
+                if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 130, 80, 25 }, NULL, &heightValue, 0, 8192, heightEditMode)) heightEditMode = !heightEditMode; 
+                GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 130, 30, 25 }, "pixels");
+                GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 180, 180, 160 }, "Pixel Format");
+                pixelFormatActive = GuiComboBox((Rectangle){ windowOffset.x + 20, windowOffset.y + 195, 160, 25 }, TextJoin(pixelFormatTextList, 8, ";"), pixelFormatActive);
+                GuiLine((Rectangle){ windowOffset.x + 20, windowOffset.y + 220, 160, 20 }, NULL);
+                
+                if (pixelFormatActive != 0) GuiDisable();
+                GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 235, 50, 20 }, "Channels:");
+                channelsActive = GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 255, 156/4, 25 }, TextJoin(channelsTextList, 4, ";"), channelsActive);
+                GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 285, 50, 20 }, "Bit Depth:");
+                bitDepthActive = GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 305, 160/3, 25 }, TextJoin(bitDepthTextList, 3, ";"), bitDepthActive);
+                GuiEnable();
+                
+                GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 355, 180, 50 }, "Header");
+                GuiLabel((Rectangle){ windowOffset.x + 25, windowOffset.y + 370, 27, 25 }, "Size:");
+                if (GuiValueBox((Rectangle){ windowOffset.x + 55, windowOffset.y + 370, 85, 25 }, NULL, &headerSizeValue, 0, 10000, headerSizeEditMode)) headerSizeEditMode = !headerSizeEditMode; 
+                GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 370, 30, 25 }, "bytes");
+                
+                btnLoadPressed = GuiButton((Rectangle){ windowOffset.x + 10, windowOffset.y + 420, 180, 30 }, "Import RAW");
+            }
+            //----------------------------------------------------------------------------------
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    if (texture.id != 0) UnloadTexture(texture);
+    
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+    
+    return 0;
+}

+ 96 - 0
gui.mod/raygui/examples/portable_window/portable_window.c

@@ -0,0 +1,96 @@
+/*******************************************************************************************
+*
+*   raygui - portable window
+*
+*   DEPENDENCIES:
+*       raylib 2.1  - Windowing/input management and drawing.
+*       raygui 2.0  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 raylib technologies (@raylibtech)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    int screenWidth = 800;
+    int screenHeight = 600;
+    
+    SetConfigFlags(FLAG_WINDOW_UNDECORATED);
+    InitWindow(screenWidth, screenHeight, "raygui - portable window");
+
+    // General variables
+    Vector2 mousePosition = { 0 };
+    Vector2 windowPosition = { 500, 200 };
+    Vector2 panOffset = mousePosition;
+    bool dragWindow = false;
+    
+    SetWindowPosition(windowPosition.x, windowPosition.y);
+    
+    bool exitWindow = false;
+    
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!exitWindow && !WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        mousePosition = GetMousePosition();
+        
+        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+        {
+            if (CheckCollisionPointRec(mousePosition, (Rectangle){ 0, 0, screenWidth, 20 }))
+            {
+                dragWindow = true;
+                panOffset = mousePosition;
+            }
+        }
+
+        if (dragWindow)
+        {            
+            windowPosition.x += (mousePosition.x - panOffset.x);
+            windowPosition.y += (mousePosition.y - panOffset.y);
+            
+            if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) dragWindow = false;
+
+            SetWindowPosition(windowPosition.x, windowPosition.y);
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            exitWindow = GuiWindowBox((Rectangle){ 0, 0, screenWidth, screenHeight }, "PORTABLE WINDOW");
+            
+            DrawText(FormatText("Mouse Position: [ %.0f, %.0f ]", mousePosition.x, mousePosition.y), 10, 40, 10, DARKGRAY);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 150 - 0
gui.mod/raygui/examples/scroll_panel/gui_scroll_panel.c

@@ -0,0 +1,150 @@
+/*******************************************************************************************
+*
+*   raygui - Controls test
+*
+*   TEST CONTROLS:
+*       - GuiScrollPanel()
+*
+*   DEPENDENCIES:
+*       raylib 2.4  - Windowing/input management and drawing.
+*       raygui 2.0  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   COMPILATION (Linux - gcc):
+*	gcc -o $(NAME_PART) $(FILE_NAME) -I../../src -lraylib -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+
+static void DrawStyleEditControls(void);  // Draw and process scroll bar style edition controls
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raygui - GuiScrollPanel()");
+    
+    Rectangle panelRec = { 20, 40, 200, 150 };
+    Rectangle panelContentRec = {0, 0, 340, 340 };
+    Vector2 panelScroll = { 99, -20 };
+    
+    bool showContentArea = true;
+    
+    SetTargetFPS(60);
+    //---------------------------------------------------------------------------------------
+    
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        // TODO: Implement required update logic
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+            
+            ClearBackground(RAYWHITE);
+            
+            DrawText(TextFormat("[%f, %f]", panelScroll.x, panelScroll.y), 4, 4, 20, RED);
+            
+            Rectangle view = GuiScrollPanel(panelRec, panelContentRec, &panelScroll);
+            
+            BeginScissorMode(view.x, view.y, view.width, view.height);
+                GuiGrid((Rectangle){panelRec.x + panelScroll.x, panelRec.y + panelScroll.y, panelContentRec.width, panelContentRec.height}, 16, 3);
+            EndScissorMode();
+            
+            if (showContentArea) DrawRectangle(panelRec.x + panelScroll.x, panelRec.y + panelScroll.y, panelContentRec.width, panelContentRec.height, Fade(RED, 0.1));
+            
+            DrawStyleEditControls();
+            
+            showContentArea = GuiCheckBox((Rectangle){ 565, 80, 20, 20 }, "SHOW CONTENT AREA", showContentArea);
+                
+            panelContentRec.width = GuiSliderBar((Rectangle){ 590, 385, 145, 15}, "WIDTH", TextFormat("%i", (int)panelContentRec.width), 1, 600, true);
+            panelContentRec.height = GuiSliderBar((Rectangle){ 590, 410, 145, 15 }, "HEIGHT", TextFormat("%i", (int)panelContentRec.height), 1, 400, true);
+            
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}
+
+// Draw and process scroll bar style edition controls
+static void DrawStyleEditControls(void)
+{
+    // ScrollPanel style controls
+    //----------------------------------------------------------
+    GuiGroupBox((Rectangle){ 550, 170, 220, 205 }, "SCROLLBAR STYLE");
+    
+    int style = GuiGetStyle(SCROLLBAR, BORDER_WIDTH);
+    GuiLabel((Rectangle){ 555, 195, 110, 10 }, "BORDER_WIDTH");
+    GuiSpinner((Rectangle){ 670, 190, 90, 20 }, NULL, &style, 0, 6, false);
+    GuiSetStyle(SCROLLBAR, BORDER_WIDTH, style);
+    
+    style = GuiGetStyle(SCROLLBAR, ARROWS_SIZE);
+    GuiLabel((Rectangle){ 555, 220, 110, 10 }, "ARROWS_SIZE");
+    GuiSpinner((Rectangle){ 670, 215, 90, 20 }, NULL, &style, 4, 14, false);
+    GuiSetStyle(SCROLLBAR, ARROWS_SIZE, style);
+    
+    style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
+    GuiLabel((Rectangle){ 555, 245, 110, 10 }, "SLIDER_PADDING");
+    GuiSpinner((Rectangle){ 670, 240, 90, 20 }, NULL, &style, 0, 14, false);
+    GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
+    
+    style = GuiCheckBox((Rectangle){ 565, 280, 20, 20 }, "ARROWS_VISIBLE", GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE));
+    GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, style);
+    
+    style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
+    GuiLabel((Rectangle){ 555, 325, 110, 10 }, "SLIDER_PADDING");
+    GuiSpinner((Rectangle){ 670, 320, 90, 20 }, NULL, &style, 0, 14, false);
+    GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
+    
+    style = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH);
+    GuiLabel((Rectangle){ 555, 350, 110, 10 }, "SLIDER_WIDTH");
+    GuiSpinner((Rectangle){ 670, 345, 90, 20 }, NULL, &style, 2, 100, false);
+    GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, style);
+    
+    const char *text = GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE? "SCROLLBAR: LEFT" : "SCROLLBAR: RIGHT";
+    style = GuiToggle((Rectangle){ 560, 110, 200, 35 }, text, GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE));
+    GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, style);
+    //----------------------------------------------------------
+
+    // ScrollBar style controls
+    //----------------------------------------------------------
+    GuiGroupBox((Rectangle){ 550, 20, 220, 135 }, "SCROLLPANEL STYLE");
+    
+    style = GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+    GuiLabel((Rectangle){ 555, 35, 110, 10 }, "SCROLLBAR_WIDTH");
+    GuiSpinner((Rectangle){ 670, 30, 90, 20 }, NULL, &style, 6, 30, false);
+    GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, style);
+    
+    style = GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    GuiLabel((Rectangle){ 555, 60, 110, 10 }, "BORDER_WIDTH");
+    GuiSpinner((Rectangle){ 670, 55, 90, 20 }, NULL, &style, 0, 20, false);
+    GuiSetStyle(DEFAULT, BORDER_WIDTH, style);
+    //----------------------------------------------------------
+}

+ 193 - 0
gui.mod/raygui/examples/standalone/custom_backend.h

@@ -0,0 +1,193 @@
+/*******************************************************************************************
+*
+*   raygui - Standalone mode custom backend
+*
+*   Just edit this file to include your custom implementation to your graphic API
+*
+*   LICENSE: <your_license>
+*
+*   Copyright (c) <year> <developer_name>
+*
+**********************************************************************************************/
+
+//#include "my_cool_graphic_api.h"
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+// TODO: Define input keys required by raygui
+//----------------------------------------------------------------------------------
+#define KEY_RIGHT           262
+#define KEY_LEFT            263
+#define KEY_DOWN            264
+#define KEY_UP              265
+#define KEY_BACKSPACE       259
+#define KEY_ENTER           257
+#define MOUSE_LEFT_BUTTON     0
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// TODO: Define required structures, maybe Font/Texture2D should be defined here?
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+// TODO: Define all raygui required functions (previously provided by raylib)
+//----------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------
+// Input required functions
+//-------------------------------------------------------------------------------
+static Vector2 GetMousePosition(void)
+{
+    Vector2 position = { 0 };
+    
+    // TODO: Mouse position
+    
+    return position;
+}
+
+static int GetMouseWheelMove(void)
+{
+    // TODO: Mouse wheel movement variation, reseted every frame
+    
+    return 0;
+}
+
+static bool IsMouseButtonDown(int button)
+{
+    // TODO: Return true while mouse button [0..2] is being down
+    
+    return false;
+}
+
+static bool IsMouseButtonPressed(int button)
+{
+    // TODO: Return true when mouse button [0..2] has been pressed: up->down
+    
+    return false;
+}
+
+static bool IsMouseButtonReleased(int button)
+{
+    // TODO: Return true when mouse button [0..2] has been released: down->up
+    
+    return false;
+}
+
+static bool IsKeyDown(int key)
+{
+    // TODO: Return true while key is being down
+    
+    return false;
+}
+
+static bool IsKeyPressed(int key)
+{
+    // TODO: Return true when key has been pressed: up->down
+    
+    return false;
+}
+
+// USED IN: GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()
+static int GetKeyPressed(void)
+{
+    // TODO: Return last key pressed (up->down) in the frame
+    
+    return 0;
+}
+
+//-------------------------------------------------------------------------------
+// Drawing required functions
+//-------------------------------------------------------------------------------
+static void DrawRectangle(int x, int y, int width, int height, Color color)
+{ 
+    // TODO: Draw rectangle on the screen
+}
+
+// USED IN: GuiColorPicker()
+static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
+{
+    // TODO: Draw rectangle with gradients (4 vertex colors) on the screen
+}
+
+// USED IN: GuiDropdownBox(), GuiScrollBar()
+static void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
+{ 
+    // TODO: Draw triangle on the screen, required for arrows
+}
+
+// USED IN: GuiImageButtonEx()
+static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
+{
+    // TODO: Draw texture (piece defined by source rectangle) on screen
+}
+
+// USED IN: GuiTextBoxMulti()
+static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
+{
+    // TODO: Draw text limited by a rectangle. This advance function wraps the text inside the rectangle
+}
+
+//-------------------------------------------------------------------------------
+// Text required functions
+//-------------------------------------------------------------------------------
+// USED IN: GuiLoadStyleDefault()
+static Font GetFontDefault(void)
+{
+    Font font = { 0 };
+    
+    // TODO: Return default rendering Font for the UI
+    
+    return font; 
+}
+
+// USED IN: GetTextWidth(), GuiTextBoxMulti()
+static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing) 
+{ 
+    Vector2 size = { 0 };
+    
+    // TODO: Return text size (width, height) on screen depending on the Font, text, fontSize and spacing
+    
+    return size;
+}
+
+// USED IN: GuiDrawText()
+static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
+{
+    // TODO: Draw text on the screen
+}
+
+//-------------------------------------------------------------------------------
+// GuiLoadStyle() required functions
+//-------------------------------------------------------------------------------
+static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount)
+{
+    Font font = { 0 };
+    
+    // TODO: Load a new font from a file
+    
+    return font; 
+}
+
+static char *LoadText(const char *fileName)
+{
+    // TODO: Load text file data, used by GuiLoadStyle() to load characters list required on Font generation,
+    // this is a .rgs feature, probably this function is not required in most cases
+
+    return NULL;
+}
+
+static const char *GetDirectoryPath(const char *filePath)
+{
+    // TODO: Get directory path for .rgs file, required to look for a possible .ttf/.otf font file referenced,
+    // this is a .rgs feature, probably this function is not required in most cases
+    
+    return NULL;
+}
+

+ 36 - 0
gui.mod/raygui/examples/standalone/raygui_standalone.c

@@ -0,0 +1,36 @@
+/*******************************************************************************************
+*
+*   raygui - Standalone mode usage template
+*
+*   DEPENDENCIES:
+*       raygui 2.6  - Immediate-mode GUI controls.
+*
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2020 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_STANDALONE
+#include "../../src/raygui.h"
+
+#include "custom_backend.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+    // TODO: Initialize your systems (window, graphics, inputs)
+    
+    // TODO: Create your game loop
+    {
+        // TODO: Use raygui API
+    }
+    
+    // TODO: De-initialize all resources
+
+    return 0;
+}

+ 301 - 0
gui.mod/raygui/examples/text_box_selection/textbox_extended_demo.c

@@ -0,0 +1,301 @@
+/*******************************************************************************************
+*
+*   raygui - Controls test
+*
+*   TEST CONTROLS:
+*       - GuiScrollPanel()
+*
+*   DEPENDENCIES:
+*       raylib 2.5  - Windowing/input management and drawing.
+*       raygui 2.0  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   COMPILATION (Linux - gcc):
+*	gcc -o $(NAME_PART) $(FILE_NAME) -I../../src -lraylib -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_RICONS
+#include "../../src/raygui.h"
+
+#undef RAYGUI_IMPLEMENTATION            // Avoid including raygui implementation again
+
+#define GUI_TEXTBOX_EXTENDED_IMPLEMENTATION
+#include "../../src/gui_textbox_extended.h"
+
+#include <limits.h>
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define SIZEOF(A) (sizeof(A)/sizeof(A[0]))  // Get number of elements in array `A`. Total size of `A` should be known at compile time.
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static char text01[92] = "Lorem ipsum dolor sit amet, \xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B consectetur adipiscing elit"; // including some hiragana/kanji
+static char text02[128] = "Here's another, much bigger textboxBounds." "\xf4\xa1\xa1\xff" " TIP: try COPY/PASTE ;)"; // including some invalid UTF8 
+
+static int textboxActive = 0; // Keeps traks of the active textboxBounds
+
+static Rectangle textboxBounds[4] = {
+    { 20, 60, 160, 25 }, 
+    { 220, 60, 300, 25 },
+    { 565, 60, 95, 25 }, 
+    { 680, 60, 100, 25 },
+};
+
+static Texture2D checked = { 0 };
+
+// Draw a color button, if clicked return true
+bool ColorButton(Rectangle bounds, Color color)
+{
+    Rectangle body = {bounds.x + 2, bounds.y + 2, bounds.width - 4, bounds.height - 4};
+    bool pressed = false;
+    
+    // Update control
+    Vector2 mouse = GetMousePosition();
+    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, bounds)) pressed = true;
+
+    // Draw control
+    DrawTexture(checked, body.x, body.y, WHITE);
+    DrawRectangleRec(body, color);
+    DrawRectangleLinesEx(bounds, 1, BLACK);
+    
+    return pressed;
+}
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raygui - gui textboxBounds extended demo");
+
+    // Generate a checked checked used by the color buttons
+	Image img = GenImageChecked(26, 26, 5, 5, RAYWHITE, DARKGRAY);
+	checked = LoadTextureFromImage(img);
+	UnloadImage(img);
+    
+    Font font = { 0 };
+    int fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+    int fontSpacing = GuiGetStyle(DEFAULT, TEXT_SPACING);
+    int padding = GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING);
+    int border = GuiGetStyle(TEXTBOX, BORDER_WIDTH);
+    Color colorFG = GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_FG)); 
+    Color colorBG = GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_BG));
+    Color *colorSelected = &colorFG;
+
+    bool showMenu = false;
+    Rectangle menuRect = { 0 };
+    
+    int spinnerValue = 0;
+    int valueBoxValue = 0;
+    
+    bool textBox01EditMode = false;
+    bool textBox02EditMode = false;
+    bool spinnerEditMode = false;
+    bool valueBoxEditMode = false;
+    
+    SetTargetFPS(60);
+    //---------------------------------------------------------------------------------------
+    
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        Vector2 mouse = GetMousePosition();
+        
+        // Check all textboxes to get the active textboxBounds
+        if (textBox01EditMode) textboxActive = 0; 
+        else if (textBox02EditMode) textboxActive = 1; 
+        else if (spinnerEditMode) textboxActive = 2; 
+        else if (valueBoxEditMode) textboxActive = 3; 
+    
+        // Show/Hide the textboxBounds menu
+        /*
+        if ((textboxActive < 2) && !showMenu && CheckCollisionPointRec(mouse, textboxBounds[textboxActive]) && IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) 
+        {
+            showMenu = true;
+            menuRect = (Rectangle){mouse.x, mouse.y, 80, 110};
+        }
+        */
+    
+        // Menu hidding logic
+        if (showMenu && IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !CheckCollisionPointRec(mouse, menuRect)) showMenu = false;
+    
+        // Fonts drag & drop logic
+        if (IsFileDropped()) 
+        {
+            int count = 0;
+            char **files = GetDroppedFiles(&count);
+            
+            if (IsFileExtension(files[0], ".ttf") || 
+                IsFileExtension(files[0], ".otf") || 
+                IsFileExtension(files[0], ".fnt"))
+            {
+                Font fnt = LoadFont(files[0]);
+                
+                if (fnt.texture.id != 0)
+                {
+                    // Font was loaded, only change font on success
+                    GuiSetFont(fnt);
+                    fontSize = fnt.baseSize;
+
+                    // Remove old font
+                    if (font.texture.id != 0) UnloadFont(font);
+                    font = fnt;
+                }
+            }
+            
+            ClearDroppedFiles();
+        }
+        
+        // Convert text to hex representation and draw it on screen
+        char hex[(((textboxActive == 1) ? SIZEOF(text02) : SIZEOF(text01)) + 1)*3 + 1];
+        char *text = (textboxActive == 1) ? text02 : text01;
+        int maxSize = (textboxActive == 1) ? SIZEOF(text02) : SIZEOF(text01);
+        for (int i = 0, j = 0; i < maxSize; ++i, j += 3) sprintf(&hex[j], "%02Xh ", (char)text[i]);
+
+        int startIdx = 0, endIdx = 0;
+        if (textboxActive < 2)
+        {
+            Vector2 sel = GuiTextBoxGetSelection();
+            startIdx = GuiTextBoxGetByteIndex(text, 0, 0, sel.x);
+            endIdx = GuiTextBoxGetByteIndex(text, 0, 0, sel.x + sel.y);
+        }
+        
+        int len = endIdx - startIdx;
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+		BeginDrawing();
+		
+            ClearBackground(RAYWHITE);
+            
+            // Draw textboxes extended
+            //---------------------------------------------------------------------------------------
+            // Set custom style
+            GuiSetStyle(DEFAULT, TEXT_SIZE, fontSize);
+            GuiSetStyle(DEFAULT, TEXT_SPACING, fontSpacing);
+            GuiSetStyle(TEXTBOX, TEXT_INNER_PADDING, padding);
+            GuiSetStyle(TEXTBOX, BORDER_WIDTH, border);
+            GuiSetStyle(TEXTBOX, COLOR_SELECTED_BG, ColorToInt(colorBG));
+            GuiSetStyle(TEXTBOX, COLOR_SELECTED_FG, ColorToInt(colorFG));
+
+            // TODO: GuiTextBoxEx() is not following editMode logic like GuiTextBox()
+            if (GuiTextBoxEx(textboxBounds[0], text01, SIZEOF(text01) - 1, textBox01EditMode)) textBox01EditMode = !textBox01EditMode;
+            if (GuiTextBoxEx(textboxBounds[1], text02, SIZEOF(text02) - 1, textBox02EditMode)) textBox02EditMode = !textBox02EditMode;
+            
+            if (GuiSpinner(textboxBounds[2], NULL, &spinnerValue, INT_MIN, INT_MAX, spinnerEditMode)) spinnerEditMode = !spinnerEditMode;
+            if (GuiValueBox(textboxBounds[3], NULL, &valueBoxValue, INT_MIN, INT_MAX, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode;
+            //---------------------------------------------------------------------------------------
+            
+            // Reset style to default
+            GuiLoadStyleDefault();
+            GuiSetFont(GetFontDefault());
+            GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+    
+            // Draw hexadecimal values viewer
+            DrawTextRecEx(guiFont, hex, (Rectangle){ 20, 95, 760, 205 }, 20, 1, true, BLACK, startIdx*3, len*3, colorFG, colorBG);
+
+            // Draw right-mouse-button-click menu and logic
+            //---------------------------------------------------------------------------------------
+            if (showMenu)
+            {
+                GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24); // make items look a little bigger
+                const char *menuItems[] = { "#17# Cut", "#16# Copy", "#18# Paste", "#101# SelectAll" };
+                //int enabledItems[] = { textboxActive < 2 ? 1 : 0, textboxActive < 2 ? 1 : 0, GetClipboardText() != NULL, 1 };
+                int active = -1, focus = 0, scroll = 0;
+                
+                GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT); // Fixes visual glitch with other alignments
+                active = GuiListViewEx(menuRect, menuItems, SIZEOF(menuItems), &focus, &scroll, active);
+                
+                if (active != -1)
+                {
+                    showMenu = false;
+                    char *text = (textboxActive == 1) ? text02 : text01;
+                    switch(active)
+                    {
+                        case 0: GuiTextBoxCut(text); break;
+                        case 1: GuiTextBoxCopy(text); break;
+                        case 2: GuiTextBoxPaste(text, (textboxActive == 1) ? SIZEOF(text02) : SIZEOF(text01)); break;
+                        case 3: GuiTextBoxSelectAll(text); break;
+                        default: break;
+                    }
+                }
+            }
+            //---------------------------------------------------------------------------------------
+    
+            // Draw GUI to change textboxes parameters
+            //---------------------------------------------------------------------------------------
+            /*
+            // UI for changing the font size and spacing of all textboxes
+            GuiLine((Rectangle){25,280,750,10}, NULL);
+            GuiGroupBox((Rectangle){20,320,190,100},  GuiIconText(RICON_GEAR, "FONT"));
+            GuiLabel((Rectangle){30,340,60,20}, "Size");
+            GuiSpinner((Rectangle){95,340,100,20}, NULL, &fontSize, 10, 40, true);
+            GuiLabel((Rectangle){30,380,60,20}, "Spacing");
+            GuiSpinner((Rectangle){95,380,100,20}, NULL, &fontSpacing, 1, 10, true);
+            
+            // UI for changing the style of all textboxes
+            GuiGroupBox((Rectangle){225,320,190,100}, GuiIconText(RICON_COLOR_BUCKET, "STYLE"));
+            GuiLabel((Rectangle){240,340,60,20}, "Padding");
+            GuiSpinner((Rectangle){305,340,100,20}, NULL, &padding, 2, 30, true);
+            GuiLabel((Rectangle){240,380,60,20}, "Border");
+            GuiSpinner((Rectangle){305,380,100,20}, NULL, &border, 0, 8, true);
+
+            // UI for changing the width/height of the active textboxBounds
+            bool changed = false;
+            int width = textboxBounds[textboxActive].width, height = textboxBounds[textboxActive].height;
+            GuiGroupBox((Rectangle){430,320,175,100}, GuiIconText(RICON_CURSOR_SCALE, "SCALE"));
+            GuiLabel((Rectangle){435,340,55,20}, "Width");
+            if (GuiSpinner((Rectangle){495,340,100,20}, NULL, &width, 30, 300, true)) changed = true;
+            GuiLabel((Rectangle){435,380,55,20}, "Height");
+            if (GuiSpinner((Rectangle){495,380,100,20}, NULL, &height, 12, 60, true)) changed = true;
+            GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+            GuiLabel((Rectangle){30,290,740,10}, GuiIconText(RICON_TEXT_T, " DRAG A FONT FILE (*.TTF, *.FNT) ANYWHERE TO CHANGE THE DEFAULT FONT!"));
+            GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+            textboxBounds[textboxActive].y = 85 - height;
+            textboxBounds[textboxActive].height = height;
+            textboxBounds[textboxActive].width = width;
+            if (changed) GuiTextBoxSetActive(textboxBounds[textboxActive]);
+            
+            // UI for selecting the selected text background and foreground color
+            if (ColorButton((Rectangle){625,320,30,30}, colorFG)) colorSelected = &colorFG;
+            if (ColorButton((Rectangle){625,389,30,30}, colorBG)) colorSelected = &colorBG;
+            *colorSelected = GuiColorPicker((Rectangle){660,320,90,85}, *colorSelected);
+            
+            float alpha = colorSelected->a;
+            GuiSetStyle(SLIDER, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT); // Slider for the selected color alpha value
+            colorSelected->a = GuiSlider((Rectangle){664,420,100,20}, GuiIconText(RICON_CROP_ALPHA, "Alpha"), NULL, alpha, 0.0f, 255.0f);
+            */
+            //---------------------------------------------------------------------------------------
+                
+		EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 297 - 0
gui.mod/raygui/examples/text_editor/text_editor.c

@@ -0,0 +1,297 @@
+/*******************************************************************************************
+*
+*   raygui - Controls test
+*
+*   TEST CONTROLS:
+*       - GuiTextEditor()
+*
+*   DEPENDENCIES:
+*       raylib 3.0  - Windowing/input management and drawing.
+*       raygui 2.7  - Immediate-mode GUI controls.
+*
+*   COMPILATION (Windows - MinGW):
+*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2020 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_SUPPORT_ICONS
+#include "../../src/raygui.h"
+
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static char text01[128] = "Lorem ipsum dolor sit amet, \xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B consectetur adipiscing elit...\0"; // including some hiragana/kanji
+static char text02[128] = "Here's another, much bigger textbox extended.\xf4\xa1\xa1\xff TIP: try COPY/PASTE ;)\0"; // Including some invalid UTF8 
+
+bool GuiTextEditor(Rectangle bounds, char *text, int textLen, bool editMode);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+    // Initialization
+    //---------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raygui - gui text editor test");
+
+    Font font = { 0 };
+
+    bool textEditor01EditMode = false;
+    bool textEditor02EditMode = false;
+    
+    SetTargetFPS(60);
+    //---------------------------------------------------------------------------------------
+    
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        Vector2 mouse = GetMousePosition();
+
+        // Fonts drag & drop logic
+        if (IsFileDropped()) 
+        {
+            int count = 0;
+            char **files = GetDroppedFiles(&count);
+            
+            if (IsFileExtension(files[0], ".ttf") || 
+                IsFileExtension(files[0], ".otf") || 
+                IsFileExtension(files[0], ".fnt"))
+            {
+                Font fnt = LoadFont(files[0]);
+                
+                if (fnt.texture.id != 0)
+                {
+                    // Font was loaded, only change font on success
+                    GuiSetFont(fnt);
+
+                    // Remove old font
+                    if (font.texture.id != 0) UnloadFont(font);
+                    font = fnt;
+                }
+            }
+            
+            ClearDroppedFiles();
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+		BeginDrawing();
+		
+            ClearBackground(RAYWHITE);
+            
+            // Draw textboxes extended
+            //---------------------------------------------------------------------------------------
+            if (GuiTextEditor((Rectangle){ 20, 20, 380, 410 }, text01, strlen(text01), textEditor01EditMode)) textEditor01EditMode = !textEditor01EditMode;
+            if (GuiTextEditor((Rectangle){ 420, 20, 360, 410 }, text02, strlen(text02), textEditor02EditMode)) textEditor02EditMode = !textEditor02EditMode;
+            //---------------------------------------------------------------------------------------
+            
+		EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}
+
+// Text editor control (Advanced text box)
+bool GuiTextEditor(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+    static Rectangle cursor = { 0 };    // Cursor position and size
+    static int framesCounter = 0;       // Blinking cursor frames counter
+    static int cursorCodepoint = -1;
+    static int selectStartCp = -1;
+    static int selectLengthCp = 0;
+    
+    GuiControlState state = guiState;
+    bool pressed = false;
+    
+    bool textWrap = true;           // TODO: Word-Wrap vs Char-Wrap -> textWrapMode { NO_WRAP_LOCK, NO_WRAP_OVERFLOW, CHAR_WRAP, WORD_WRAP }
+
+    // WARNING: First string full traversal
+    int codepointCount = GetCodepointsCount(text);
+    
+    int textLen = strlen(text);     // Text length in bytes
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (editMode)
+        {
+            state = GUI_STATE_PRESSED;
+            framesCounter++;
+            
+            // TODO: Cursor position logic (mouse and keys)
+            
+            // Characters selection logic
+            if (selectStartCp != -1)
+            {
+                if (IsKeyDown(KEY_LEFT_SHIFT) && IsKeyPressed(KEY_RIGHT))
+                {
+                    selectLengthCp++;
+                    if (selectLengthCp >= (codepointCount - selectStartCp)) selectLengthCp = codepointCount - selectStartCp;
+                }
+                
+                if (IsKeyDown(KEY_LEFT_SHIFT) && IsKeyPressed(KEY_LEFT))
+                {
+                    selectLengthCp--;
+                    if (selectLengthCp < 0) selectLengthCp = 0;
+                }
+            }
+            
+            int key = GetKeyPressed();
+            
+            // TODO: On key pressed, place new character in cursor position
+
+            // Exit edit mode logic
+            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(0))) pressed = true;
+        }
+        else
+        {
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                state = GUI_STATE_FOCUSED;
+                if (IsMouseButtonPressed(0)) pressed = true;
+            }
+        }
+
+        if (pressed) 
+        {
+            // Exiting edit mode, reset temp variables
+            framesCounter = 0;
+            cursor = (Rectangle){ 0 };
+            
+            cursorCodepoint = -1;
+            selectStartCp = -1;
+            selectLengthCp = 0;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha));
+
+    if (state == GUI_STATE_PRESSED) DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
+    else if (state == GUI_STATE_DISABLED) DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
+
+    Font font = GetFontDefault();
+    
+    int textOffsetY = 0;            // Offset between lines (on line break '\n')
+    float textOffsetX = 0.0f;       // Offset X to next character to draw
+    
+    float scaleFactor = GuiGetStyle(DEFAULT, TEXT_SIZE)*2/font.baseSize;     // Character quad scaling factor
+    
+    for (int i = 0, cp = 0; i < textLen; i++)
+    {
+        // Get next codepoint from byte string and glyph index in font
+        int codepointByteCount = 0;
+        int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
+        int index = GetGlyphIndex(font, codepoint);
+        
+        Rectangle rec = { bounds.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
+                          bounds.y + textOffsetY + font.chars[index].offsetY*scaleFactor, 
+                          font.recs[index].width*scaleFactor, font.recs[index].height*scaleFactor };
+                          
+        // Automatic line break to wrap text inside box
+        if (textWrap && ((rec.x + rec.width) >= (bounds.x + bounds.width)))
+        {
+            textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
+            textOffsetX = 0.0f;
+            
+            // Recalculate drawing rectangle position
+            rec = (Rectangle){ bounds.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
+                               bounds.y + textOffsetY + font.chars[index].offsetY*scaleFactor, 
+                               font.recs[index].width*scaleFactor, font.recs[index].height*scaleFactor };
+        }
+        
+        // Check selected codepoint
+        if (editMode)
+        {
+            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(GetMousePosition(), rec))
+            {
+                cursor = rec;
+                cursorCodepoint = cp;
+                selectStartCp = cursorCodepoint;
+                selectLengthCp = 0;
+                
+                // TODO: Place cursor at the end if pressed out of text
+            }
+            
+            // On mouse left button down allow text selection
+            if ((selectStartCp != -1) && IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(GetMousePosition(), rec))
+            {
+                if (cp >= selectStartCp) selectLengthCp = cp - selectStartCp;
+                else if (cp < selectStartCp) 
+                { 
+                    //int temp = selectStartCp;
+                    //selectStartCp = cp;
+                    //selectLengthCp = temp - selectStartCp;
+                }
+            }
+        }
+        
+
+        
+        if (codepoint == '\n')    // Line break character
+        {
+            // NOTE: Fixed line spacing of 1.5 line-height
+            // TODO: Support custom line spacing defined by user
+            textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
+            textOffsetX = 0.0f;
+        }
+        else
+        {
+            // Draw codepoint glyph
+            if ((codepoint != ' ') && (codepoint != '\t') && ((rec.x + rec.width) < (bounds.x + bounds.width)))
+            {
+                DrawTexturePro(font.texture, font.recs[index], rec, (Vector2){ 0, 0 }, 0.0f, GetColor(GuiGetStyle(DEFAULT, TEXT_COLOR_NORMAL)));
+            }
+            
+            // TODO: On text overflow do something... move text to the left?
+        }
+        
+        // Draw codepoints selection from selectStartCp to selectLengthCp
+        // TODO: Consider spacing when drawing selected characters background
+        if (editMode && (selectStartCp != -1) && ((cp >= selectStartCp) && (cp <= (selectStartCp + selectLengthCp)))) DrawRectangleRec(rec, MAROON);
+        
+        if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + GuiGetStyle(DEFAULT, TEXT_SPACING));
+        else textOffsetX += ((float)font.chars[index].advanceX*scaleFactor + GuiGetStyle(DEFAULT, TEXT_SPACING));
+        
+        i += (codepointByteCount - 1);   // Move text bytes counter to next codepoint
+        cp++;
+    }
+    
+    // Draw blinking cursor
+    if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangleRec(cursor, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+
+    //GuiDrawText(text, GetTextBounds(TEXTBOX, bounds), GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return pressed;
+}

二进制
gui.mod/raygui/images/raygui_controls_panel.png


二进制
gui.mod/raygui/images/raygui_ricons.png


二进制
gui.mod/raygui/images/raygui_style_table_multi.png


二进制
gui.mod/raygui/images/rguistyler_v210.png


二进制
gui.mod/raygui/images/rguistyler_v300.png


二进制
gui.mod/raygui/logo/raygui.ico


二进制
gui.mod/raygui/logo/raygui_128x128.png


二进制
gui.mod/raygui/logo/raygui_16x16.png


二进制
gui.mod/raygui/logo/raygui_24x24.png


二进制
gui.mod/raygui/logo/raygui_256x256.png


二进制
gui.mod/raygui/logo/raygui_32x32.png


二进制
gui.mod/raygui/logo/raygui_48x48.png


二进制
gui.mod/raygui/logo/raygui_64x64.png


二进制
gui.mod/raygui/logo/raygui_96x96.png


+ 182 - 0
gui.mod/raygui/projects/VS2017/examples/controls_test_suite.vcxproj

@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug.DLL|Win32">
+      <Configuration>Debug.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release.DLL|Win32">
+      <Configuration>Release.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0981CA98-E4A5-4DF1-987F-A41D09131EFC}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>controls_test_suite</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+    <ProjectName>controls_test_suite</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\raylib\src;$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\examples\controls_test_suite\controls_test_suite.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\raylib\raylib.vcxproj">
+      <Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 55 - 0
gui.mod/raygui/projects/VS2017/raygui.sln

@@ -0,0 +1,55 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2024
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "controls_test_suite", "examples\controls_test_suite.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raylib", "raylib\raylib.vcxproj", "{E89D61AC-55DE-4482-AFD4-DF7242EBC859}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug.DLL|x86 = Debug.DLL|x86
+		Debug|x86 = Debug|x86
+		Release.DLL|x86 = Release.DLL|x86
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.ActiveCfg = Debug|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.Build.0 = Debug|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.ActiveCfg = Release|Win32
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.Build.0 = Release|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x86.ActiveCfg = Debug|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Debug|x86.Build.0 = Debug|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x86.ActiveCfg = Release|Win32
+		{E89D61AC-55DE-4482-AFD4-DF7242EBC859}.Release|x86.Build.0 = Release|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Debug|x86.ActiveCfg = Debug|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Debug|x86.Build.0 = Debug|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Release|x86.ActiveCfg = Release|Win32
+		{B655E850-3322-42F7-941D-6AC18FD66CA1}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{0981CA98-E4A5-4DF1-987F-A41D09131EFC} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
+		{B655E850-3322-42F7-941D-6AC18FD66CA1} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
+	EndGlobalSection
+EndGlobal

+ 192 - 0
gui.mod/raygui/projects/VS2017/raylib/raylib.vcxproj

@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug.DLL|Win32">
+      <Configuration>Debug.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release.DLL|Win32">
+      <Configuration>Release.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{E89D61AC-55DE-4482-AFD4-DF7242EBC859}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>raylib</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)$(ProjectName)\$(Configuration)\temp</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\raylib\release\include;$(SolutionDir)..\..\..\raylib\src\external\glfw\include</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\..\raylib\release\include;$(SolutionDir)..\..\..\raylib\src\external\glfw\include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\raylib\release\include;$(SolutionDir)..\..\..\raylib\src\external\glfw\include</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);GRAPHICS_API_OPENGL_33;PLATFORM_DESKTOP;BUILD_LIBTYPE_SHARED</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\raylib\release\include;$(SolutionDir)..\..\..\raylib\src\external\glfw\include</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\raylib\src\raudio.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\core.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\models.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\rglfw.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\shapes.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\text.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\textures.c" />
+    <ClCompile Include="..\..\..\..\raylib\src\utils.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\raylib\src\camera.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\glad.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\jar_mod.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\jar_xm.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\miniaudio.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_image.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_image_resize.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_image_write.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_rect_pack.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_truetype.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\external\stb_vorbis.h" />
+    <ClInclude Include="..\..\..\..\raylib\\src\gestures.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\raylib.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\raymath.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\rlgl.h" />
+    <ClInclude Include="..\..\..\..\raylib\src\utils.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 1072 - 0
gui.mod/raygui/src/gui_textbox_extended.h

@@ -0,0 +1,1072 @@
+/*******************************************************************************************
+*
+*   Text box extended (cursor positioning and editing)
+*
+*   MODULE USAGE:
+*       #define GUI_TEXTBOX_EXTENDED_IMPLEMENTATION
+*       #include "gui_textbox_extended.h"
+*
+*   On game draw call:  GuiTextBoxEx(...);
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5)
+*
+*   This software is provided "as-is", without any express or implied warranty. In no event
+*   will the authors be held liable for any damages arising from the use of this software.
+*
+*   Permission is granted to anyone to use this software for any purpose, including commercial
+*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+*     1. The origin of this software must not be misrepresented; you must not claim that you
+*     wrote the original software. If you use this software in a product, an acknowledgment
+*     in the product documentation would be appreciated but is not required.
+*
+*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
+*     as being the original software.
+*
+*     3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef GUI_TEXTBOX_EXTENDED_H
+#define GUI_TEXTBOX_EXTENDED_H
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+// Text box state data
+typedef struct GuiTextBoxState {
+    int cursor;      // Cursor position in text
+    int start;       // Text start position (from where we begin drawing the text)
+    int index;       // Text start index (index inside the text of `start` always in sync)
+    int select;      // Marks position of cursor when selection has started
+} GuiTextBoxState;
+
+#ifdef __cplusplus
+extern "C" {            // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+RAYGUIDEF void GuiTextBoxSetActive(Rectangle bounds);                   // Sets the active textbox
+RAYGUIDEF Rectangle GuiTextBoxGetActive(void);                          // Get bounds of active textbox
+
+RAYGUIDEF void GuiTextBoxSetCursor(int cursor);                         // Set cursor position of active textbox
+RAYGUIDEF int GuiTextBoxGetCursor(void);                                // Get cursor position of active textbox
+
+RAYGUIDEF void GuiTextBoxSetSelection(int start, int length);           // Set selection of active textbox
+RAYGUIDEF Vector2 GuiTextBoxGetSelection(void);                         // Get selection of active textbox (x - selection start  y - selection length)
+
+RAYGUIDEF bool GuiTextBoxIsActive(Rectangle bounds);                    // Returns true if a textbox control with specified `bounds` is the active textbox
+RAYGUIDEF GuiTextBoxState GuiTextBoxGetState(void);                     // Get state for the active textbox
+RAYGUIDEF void GuiTextBoxSetState(GuiTextBoxState state);               // Set state for the active textbox (state must be valid else things will break)
+
+RAYGUIDEF void GuiTextBoxSelectAll(const char *text);                   // Select all characters in the active textbox (same as pressing `CTRL` + `A`)
+RAYGUIDEF void GuiTextBoxCopy(const char *text);                        // Copy selected text to clipboard from the active textbox (same as pressing `CTRL` + `C`)
+RAYGUIDEF void GuiTextBoxPaste(char *text, int textSize);               // Paste text from clipboard into the textbox (same as pressing `CTRL` + `V`)
+RAYGUIDEF void GuiTextBoxCut(char *text);                               // Cut selected text in the active textbox and copy it to clipboard (same as pressing `CTRL` + `X`)
+RAYGUIDEF int GuiTextBoxDelete(char *text, int length, bool before);    // Deletes a character or selection before from the active textbox (depending on `before`). Returns bytes deleted.
+RAYGUIDEF int GuiTextBoxGetByteIndex(const char *text, int start, int from, int to); // Get the byte index for a character starting at position `from` with index `start` until position `to`.
+
+RAYGUIDEF bool GuiTextBoxEx(Rectangle bounds, char *text, int textSize, bool editMode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUI_TEXTBOX_EXTENDED_H
+
+/***********************************************************************************
+*
+*   GUI TEXTBOX EXTENDED IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(GUI_TEXTBOX_EXTENDED_IMPLEMENTATION)
+
+#include "raygui.h"
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Cursor measure mode
+typedef enum {
+    GUI_MEASURE_MODE_CURSOR_END = 0xA,
+    GUI_MEASURE_MODE_CURSOR_POS,
+    GUI_MEASURE_MODE_CURSOR_COORDS
+} GuiMeasureMode;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static Rectangle guiTextBoxActive = { 0 };      // Area of the currently active textbox
+
+static GuiTextBoxState guiTextBoxState = {      // Keeps state of the active textbox
+    .cursor = -1,
+    .start = 0,
+    .index = 0,
+    .select = -1 
+};
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Declaration
+//----------------------------------------------------------------------------------
+static int GetPrevCodepoint(const char *text, const char *start, int *prev);
+static int GuiMeasureTextBox(const char *text, int length, Rectangle rec, int *pos, int mode);
+static int GuiMeasureTextBoxRev(const char *text, int length, Rectangle rec, int *pos);                 // Highly synchronized with calculations in DrawTextRecEx()
+
+static inline int GuiTextBoxGetCursorCoordinates(const char *text, int length, Rectangle rec, int pos); // Calculate cursor coordinates based on the cursor position `pos` inside the `text`.
+static inline int GuiTextBoxGetCursorFromMouse(const char *text, int length, Rectangle rec, int *pos);  // Calculate cursor position in textbox based on mouse coordinates.
+static inline int GuiTextBoxMaxCharacters(const char *text, int length, Rectangle rec);                 // Calculates how many characters is the textbox able to draw inside rec
+static inline unsigned int GuiCountCodepointsUntilNewline(const char *text);    // Returns total number of characters(codepoints) in a UTF8 encoded `text` until `\0` or a `\n` is found.
+
+static inline void MoveTextBoxCursorRight(const char *text, int length, Rectangle textRec);
+static inline void MoveTextBoxCursorLeft(const char *text);
+
+static int EncodeCodepoint(unsigned int c, char out[5]);
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Sets the active textbox (reseting state of the previous active textbox)
+RAYGUIDEF void GuiTextBoxSetActive(Rectangle bounds)
+{
+    guiTextBoxActive = bounds;
+    guiTextBoxState = (GuiTextBoxState){ .cursor = -1, .start = 0, .index = 0, .select = -1 };
+}
+
+// Gets bounds of active textbox
+RAYGUIDEF Rectangle GuiTextBoxGetActive(void) { return guiTextBoxActive; }
+
+// Set cursor position of active textbox
+RAYGUIDEF void GuiTextBoxSetCursor(int cursor)
+{
+    guiTextBoxState.cursor = (cursor < 0) ? -1 : cursor;
+    guiTextBoxState.start = -1; // Mark this to be recalculated
+}
+
+// Get cursor position of active textbox
+RAYGUIDEF int GuiTextBoxGetCursor(void) { return guiTextBoxState.cursor; }
+
+// Set selection of active textbox
+RAYGUIDEF void GuiTextBoxSetSelection(int start, int length)
+{
+    if (start < 0) start = 0;
+    if (length < 0) length = 0;
+
+    GuiTextBoxSetCursor(start + length);
+    guiTextBoxState.select = start;
+}
+
+// Get selection of active textbox
+RAYGUIDEF Vector2 GuiTextBoxGetSelection(void)
+{
+    if (guiTextBoxState.select == -1 || guiTextBoxState.select == guiTextBoxState.cursor) return RAYGUI_CLITERAL(Vector2){ 0 };
+    else if (guiTextBoxState.cursor > guiTextBoxState.select) return RAYGUI_CLITERAL(Vector2){ guiTextBoxState.select, guiTextBoxState.cursor - guiTextBoxState.select };
+
+    return RAYGUI_CLITERAL(Vector2){ guiTextBoxState.cursor, guiTextBoxState.select - guiTextBoxState.cursor };
+}
+
+// Returns true if a textbox control with specified `bounds` is the active textbox
+RAYGUIDEF bool GuiTextBoxIsActive(Rectangle bounds)
+{
+    return (bounds.x == guiTextBoxActive.x && bounds.y == guiTextBoxActive.y &&
+            bounds.width == guiTextBoxActive.width && bounds.height == guiTextBoxActive.height);
+}
+
+RAYGUIDEF GuiTextBoxState GuiTextBoxGetState(void) { return guiTextBoxState; }
+RAYGUIDEF void GuiTextBoxSetState(GuiTextBoxState state)
+{
+    // NOTE: should we check if state values are valid ?!?
+    guiTextBoxState = state;
+}
+
+RAYGUIDEF int GuiTextBoxGetByteIndex(const char *text, int start, int from, int to)
+{
+    int i = start, k = from;
+
+    while ((text[i] != '\0') && (k < to))
+    {
+        int j = 0;
+        int letter = GetNextCodepoint(&text[i], &j);
+
+        if (letter == 0x3f) j = 1;
+        i += j;
+        ++k;
+    }
+
+    return i;
+}
+
+RAYGUIDEF int GuiTextBoxDelete(char *text, int length, bool before)
+{
+    if ((guiTextBoxState.cursor != -1) && (text != NULL))
+    {
+        int startIdx = 0, endIdx = 0;
+        if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor))
+        {
+            // Delete selection
+            int start = guiTextBoxState.cursor;
+            int end = guiTextBoxState.select;
+
+            if (guiTextBoxState.cursor > guiTextBoxState.select)
+            {
+                start = guiTextBoxState.select;
+                end = guiTextBoxState.cursor;
+            }
+
+            // Convert to byte indexes
+            startIdx = GuiTextBoxGetByteIndex(text, 0, 0, start);
+            endIdx = GuiTextBoxGetByteIndex(text, 0, 0, end);
+
+            // Adjust text box state
+            guiTextBoxState.cursor = start; // Always set cursor to start of selection
+            if (guiTextBoxState.select < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate on the next frame
+        }
+        else
+        {
+            if (before)
+            {
+                // Delete character before cursor
+                if (guiTextBoxState.cursor != 0)
+                {
+                    endIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+                    guiTextBoxState.cursor--;
+                    startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+
+                    if (guiTextBoxState.cursor < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate on the next frame
+                }
+            }
+            else
+            {
+                // Delete character after cursor
+                if (guiTextBoxState.cursor + 1 <= GuiCountCodepointsUntilNewline(text))
+                {
+                    startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+                    endIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor+1);
+                }
+            }
+        }
+
+        memmove(&text[startIdx], &text[endIdx], length - endIdx);
+        text[length - (endIdx - startIdx)] = '\0';
+        guiTextBoxState.select = -1; // Always deselect
+
+        return (endIdx - startIdx);
+    }
+
+    return 0;
+}
+
+RAYGUIDEF void GuiTextBoxSelectAll(const char *text)
+{
+    guiTextBoxState.cursor = GuiCountCodepointsUntilNewline(text);
+
+    if (guiTextBoxState.cursor > 0)
+    {
+        guiTextBoxState.select = 0;
+        guiTextBoxState.start = -1; // Force recalculate on the next frame
+    }
+    else guiTextBoxState.select = -1;
+}
+
+RAYGUIDEF void GuiTextBoxCopy(const char *text)
+{
+    if ((text != NULL) &&
+        (guiTextBoxState.select != -1) &&
+        (guiTextBoxState.cursor != -1) &&
+        (guiTextBoxState.select != guiTextBoxState.cursor))
+    {
+        int start = guiTextBoxState.cursor;
+        int end = guiTextBoxState.select;
+
+        if (guiTextBoxState.cursor > guiTextBoxState.select)
+        {
+            start = guiTextBoxState.select;
+            end = guiTextBoxState.cursor;
+        }
+
+        // Convert to byte indexes
+        start = GuiTextBoxGetByteIndex(text, 0, 0, start);
+        end = GuiTextBoxGetByteIndex(text, 0, 0, end);
+
+        // FIXME: `TextSubtext()` only lets use copy TEXTSPLIT_MAX_TEXT_LENGTH (1024) bytes
+        // maybe modify `SetClipboardText()` so we can use it only on part of a string
+        const char *clipText = TextSubtext(text, start, end - start);
+
+        SetClipboardText(clipText);
+    }
+}
+
+// Paste text from clipboard into the active textbox.
+// `text` is the pointer to the buffer used by the textbox while `textSize` is the text buffer max size
+RAYGUIDEF void GuiTextBoxPaste(char *text, int textSize)
+{
+    const char *clipText = GetClipboardText(); // GLFW guaratees this should be UTF8 encoded!
+    int length = strlen(text);
+
+    if ((text != NULL) && (clipText != NULL) && (guiTextBoxState.cursor != -1))
+    {
+        if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor))
+        {
+            // If there's a selection we'll have to delete it first
+            length -= GuiTextBoxDelete(text, length, true);
+        }
+
+        int clipLen = strlen(clipText); // We want the length in bytes
+
+        // Calculate how many bytes can we copy from clipboard text before we run out of space
+        int size = ((length + clipLen) <= textSize) ? clipLen : textSize - length;
+
+        // Make room by shifting to right the bytes after cursor
+        int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+        int endIdx = startIdx + size;
+        memmove(&text[endIdx], &text[startIdx], length - startIdx);
+        text[length + size] = '\0'; // Set the NULL char
+
+        // At long last copy the clipboard text
+        memcpy(&text[startIdx], clipText, size);
+
+        // Set cursor position at the end of the pasted text
+        guiTextBoxState.cursor = 0;
+
+        for (int i = 0; i < (startIdx + size); guiTextBoxState.cursor++)
+        {
+            int next = 0;
+            int letter = GetNextCodepoint(&text[i], &next);
+            if (letter != 0x3f) i += next;
+            else i += 1;
+        }
+
+        guiTextBoxState.start = -1; // Force to recalculate on the next frame
+    }
+}
+
+RAYGUIDEF void GuiTextBoxCut(char* text)
+{
+    if ((text != NULL) &&
+        (guiTextBoxState.select != -1) &&
+        (guiTextBoxState.cursor != -1) &&
+        (guiTextBoxState.select != guiTextBoxState.cursor))
+    {
+        // First copy selection to clipboard;
+        int start = guiTextBoxState.cursor, end = guiTextBoxState.select;
+
+        if (guiTextBoxState.cursor > guiTextBoxState.select)
+        {
+            start = guiTextBoxState.select;
+            end = guiTextBoxState.cursor;
+        }
+
+        // Convert to byte indexes
+        int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, start);
+        int endIdx = GuiTextBoxGetByteIndex(text, 0, 0, end);
+
+        // FIXME: `TextSubtext()` only lets use copy TEXTSPLIT_MAX_TEXT_LENGTH (1024) bytes
+        // maybe modify `SetClipboardText()` so we can use it only on parts of a string
+        const char *clipText = TextSubtext(text, startIdx, endIdx - startIdx);
+        SetClipboardText(clipText);
+
+        // Now delete selection (copy data over it)
+        int len = strlen(text);
+        memmove(&text[startIdx], &text[endIdx], len - endIdx);
+        text[len - (endIdx - startIdx)] = '\0';
+
+        // Adjust text box state
+        guiTextBoxState.cursor = start; // Always set cursor to start of selection
+        if (guiTextBoxState.select < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate
+        guiTextBoxState.select = -1;    // Deselect
+    }
+}
+
+// A text box control supporting text selection, cursor positioning and commonly used keyboard shortcuts.
+// NOTE 1: Requires static variables: framesCounter
+// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
+RAYGUIDEF bool GuiTextBoxEx(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+    // Define the cursor movement/selection speed when movement keys are held/pressed
+    #define TEXTBOX_CURSOR_COOLDOWN   5
+
+    static int framesCounter = 0;           // Required for blinking cursor
+
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    // Make sure length doesn't exceed `textSize`. `textSize` is actually the max amount of characters the textbox can handle.
+    int length = strlen(text);
+    if (length > textSize)
+    {
+        text[textSize] = '\0';
+        length = textSize;
+    }
+
+    // Make sure we have enough room to draw at least 1 character
+    if ((bounds.width - 2*GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)) < GuiGetStyle(DEFAULT, TEXT_SIZE))
+    {
+        bounds.width = GuiGetStyle(DEFAULT, TEXT_SIZE) + 2*GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING);
+    }
+
+    // Center the text vertically
+    int verticalPadding = (bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH) - GuiGetStyle(DEFAULT, TEXT_SIZE))/2;
+
+    if (verticalPadding < 0)
+    {
+        // Make sure the height is sufficient
+        bounds.height = 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(DEFAULT, TEXT_SIZE);
+        verticalPadding = 0;
+    }
+
+    // Calculate the drawing area for the text inside the control `bounds`
+    Rectangle textRec = { bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
+                          bounds.y + verticalPadding + GuiGetStyle(TEXTBOX, BORDER_WIDTH),
+                          bounds.width - 2*(GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING) + GuiGetStyle(TEXTBOX, BORDER_WIDTH)),
+                          GuiGetStyle(DEFAULT, TEXT_SIZE) };
+
+    Vector2 cursorPos = { textRec.x, textRec.y };   // This holds the coordinates inside textRec of the cursor at current position and will be recalculated later
+    bool active = GuiTextBoxIsActive(bounds);       // Check if this textbox is the global active textbox
+
+    int selStart = 0, selLength = 0, textStartIndex = 0;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (editMode)
+        {
+            // Check if we are the global active textbox
+            // A textbox becomes active when the user clicks it :)
+            if (!active)
+            {
+                if (CheckCollisionPointRec(mousePoint, bounds) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)))
+                {
+                    // Hurray!!! we just became the active textbox
+                    active = true;
+                    GuiTextBoxSetActive(bounds);
+                }
+            }
+            else if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_RIGHT_BUTTON))
+            {
+                // When active and the right mouse is clicked outside the textbox we should deactivate it
+                // NOTE: We set a dummy rect as the active textbox bounds
+                GuiTextBoxSetActive(RAYGUI_CLITERAL(Rectangle){ 0, 0, -1, -1 });
+                active = false;
+            }
+
+            if (active)
+            {
+                state = GUI_STATE_PRESSED;
+                framesCounter++;
+
+                // Make sure state doesn't have invalid values
+                if (guiTextBoxState.cursor > length) guiTextBoxState.cursor = -1;
+                if (guiTextBoxState.select > length) guiTextBoxState.select = -1;
+                if (guiTextBoxState.start > length) guiTextBoxState.start = -1;
+
+
+                // Check textbox state for changes and recalculate if necesary
+                if (guiTextBoxState.cursor == -1)
+                {
+                    // Set cursor to last visible character in textbox
+                    guiTextBoxState.cursor = GuiTextBoxMaxCharacters(text, length, textRec);
+                }
+
+                if (guiTextBoxState.start == -1)
+                {
+                    // Force recalculate text start position and text start index
+
+                    // NOTE: start and index are always in sync
+                    // start will hold the starting character position from where the text will be drawn
+                    // while index will hold the byte index inside the text for that character
+
+                    if (guiTextBoxState.cursor == 0)
+                    {
+                        guiTextBoxState.start = guiTextBoxState.index = 0; // No need to recalculate
+                    }
+                    else
+                    {
+                        int pos = 0;
+                        int len =  GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+                        guiTextBoxState.index = GuiMeasureTextBoxRev(text, len, textRec, &pos);
+                        guiTextBoxState.start = guiTextBoxState.cursor - pos + 1;
+                    }
+                }
+
+                // -----------------
+                // HANDLE KEY INPUT
+                // -----------------
+                // * -> | LSHIFT + -> move cursor to the right | increase selection by one
+                // * <- | LSHIFT + <- move cursor to the left | decrease selection by one
+                // * HOME | LSHIFT + HOME moves cursor to start of text | selects text from cursor to start of text
+                // * END | LSHIFT + END move cursor to end of text | selects text from cursor until end of text
+                // * CTRL + A select all characters in text
+                // * CTRL + C copy selected text
+                // * CTRL + X cut selected text
+                // * CTRL + V remove selected text, if any, then paste clipboard data
+                // * DEL delete character or selection after cursor
+                // * BACKSPACE delete character or selection before cursor
+                // TODO: Add more shortcuts (insert mode, select word, moveto/select prev/next word ...)
+                if (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (framesCounter%TEXTBOX_CURSOR_COOLDOWN == 0)))
+                {
+                    if (IsKeyDown(KEY_LEFT_SHIFT))
+                    {
+                        // Selecting
+                        if (guiTextBoxState.select == -1) guiTextBoxState.select = guiTextBoxState.cursor; // Mark selection start
+
+                        MoveTextBoxCursorRight(text, length, textRec);
+                    }
+                    else
+                    {
+                        if (guiTextBoxState.select != -1 && guiTextBoxState.select != guiTextBoxState.cursor)
+                        {
+                            // Deselect and move cursor to end of selection
+                            if (guiTextBoxState.cursor < guiTextBoxState.select)
+                            {
+                                guiTextBoxState.cursor = guiTextBoxState.select - 1;
+                                MoveTextBoxCursorRight(text, length, textRec);
+                            }
+                        }
+                        else
+                        {
+                            // Move cursor to the right
+                            MoveTextBoxCursorRight(text, length, textRec);
+                        }
+
+                        guiTextBoxState.select = -1;
+                    }
+
+                    framesCounter = 0;
+                }
+                else if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (framesCounter%TEXTBOX_CURSOR_COOLDOWN == 0)))
+                {
+                    if (IsKeyDown(KEY_LEFT_SHIFT))
+                    {
+                        // Selecting
+                        if (guiTextBoxState.select == -1) guiTextBoxState.select = guiTextBoxState.cursor; // Mark selection start
+
+                        MoveTextBoxCursorLeft(text);
+                    }
+                    else
+                    {
+                        if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor))
+                        {
+                            // Deselect and move cursor to start of selection
+                            if (guiTextBoxState.cursor > guiTextBoxState.select)
+                            {
+                                guiTextBoxState.cursor = guiTextBoxState.select;
+
+                                if (guiTextBoxState.start > guiTextBoxState.cursor)
+                                {
+                                    guiTextBoxState.start = guiTextBoxState.cursor;
+                                    guiTextBoxState.index = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.start); // Recalculate byte index
+                                }
+                            }
+                        }
+                        else
+                        {
+                            // Move cursor to the left
+                            MoveTextBoxCursorLeft(text);
+                        }
+
+                        guiTextBoxState.select = -1;
+                    }
+
+                    framesCounter = 0;
+                }
+                else if (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (framesCounter%TEXTBOX_CURSOR_COOLDOWN) == 0))
+                {
+                    GuiTextBoxDelete(text, length, true);
+                }
+                else if (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (framesCounter%TEXTBOX_CURSOR_COOLDOWN) == 0))
+                {
+                    GuiTextBoxDelete(text, length, false);
+                }
+                else if (IsKeyPressed(KEY_HOME))
+                {
+                    if (IsKeyDown(KEY_LEFT_SHIFT))
+                    {
+                        // Select from start of text to cursor
+                        if ((guiTextBoxState.select > guiTextBoxState.cursor) || ((guiTextBoxState.select == -1) && (guiTextBoxState.cursor != 0)))
+                        {
+                            guiTextBoxState.select = guiTextBoxState.cursor;
+                        }
+                    }
+                    else guiTextBoxState.select = -1; // Deselect everything
+
+                    // Move cursor to start of text
+                    guiTextBoxState.cursor = guiTextBoxState.start = guiTextBoxState.index = 0;
+                    framesCounter = 0;
+                }
+                else if (IsKeyPressed(KEY_END))
+                {
+                    int max = GuiCountCodepointsUntilNewline(text);
+
+                    if (IsKeyDown(KEY_LEFT_SHIFT))
+                    {
+                        if ((guiTextBoxState.select == -1) && (guiTextBoxState.cursor != max))
+                        {
+                            guiTextBoxState.select = guiTextBoxState.cursor;
+                        }
+                    }
+                    else guiTextBoxState.select = -1; // Deselect everything
+
+                    int pos = 0;
+                    guiTextBoxState.cursor = max;
+                    int len = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+                    guiTextBoxState.index = GuiMeasureTextBoxRev(text, len, textRec, &pos);
+                    guiTextBoxState.start = guiTextBoxState.cursor - pos + 1;
+                }
+                else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_A)) GuiTextBoxSelectAll(text); // CTRL + A > Select all
+                else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) GuiTextBoxCopy(text);      // CTRL + C > Copy selected text to clipboard
+                else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_X)) GuiTextBoxCut(text);       // CTRL + X > Cut selected text
+                else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) GuiTextBoxPaste(text, textSize); // CTRL + V > Paste clipboard text
+                else if (IsKeyPressed(KEY_ENTER)) pressed = true;
+                else
+                {
+                    int key = GetKeyPressed();
+                    if ((key >= 32) && ((guiTextBoxState.cursor + 1) < textSize))
+                    {
+                        if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor))
+                        {
+                            // Delete selection
+                            GuiTextBoxDelete(text, length, true);
+                        }
+
+                        // Decode codepoint
+                        char out[5] = {0};
+                        int sz = EncodeCodepoint(key, &out[0]);
+
+                        if (sz != 0)
+                        {
+                            int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor);
+                            int endIdx = startIdx + sz;
+
+                            if (endIdx <= textSize && length < textSize - 1)
+                            {
+                                guiTextBoxState.cursor++;
+                                guiTextBoxState.select = -1;
+                                memmove(&text[endIdx], &text[startIdx], length - startIdx);
+                                memcpy(&text[startIdx], &out[0], sz);
+                                length += sz;
+                                text[length] = '\0';
+
+                                if (guiTextBoxState.start != -1)
+                                {
+                                    const int max = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec);
+
+                                    if ((guiTextBoxState.cursor - guiTextBoxState.start) > max) guiTextBoxState.start = -1;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                // -------------
+                // HANDLE MOUSE
+                // -------------
+                if (CheckCollisionPointRec(mousePoint, bounds))
+                {
+                    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+                    {
+                        if (CheckCollisionPointRec(mousePoint, textRec))
+                        {
+                            GuiTextBoxGetCursorFromMouse(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, &guiTextBoxState.cursor);
+                            guiTextBoxState.cursor += guiTextBoxState.start;
+                            guiTextBoxState.select = -1;
+                        }
+                        else
+                        {
+                            // Clicked outside the `textRec` but still inside bounds
+                            if (mousePoint.x <= bounds.x+bounds.width/2) guiTextBoxState.cursor = 0 + guiTextBoxState.start;
+                            else guiTextBoxState.cursor = guiTextBoxState.start + GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec);
+                            guiTextBoxState.select = -1;
+                        }
+                    }
+                    else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+                    {
+                        int cursor = guiTextBoxState.cursor - guiTextBoxState.start;
+                        bool move = false;
+                        if (CheckCollisionPointRec(mousePoint, textRec))
+                        {
+                            GuiTextBoxGetCursorFromMouse(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, &cursor);
+                        }
+                        else
+                        {
+                            // Clicked outside the `textRec` but still inside bounds, this means that we must move the text
+                            move = true;
+                            if (mousePoint.x > bounds.x+bounds.width/2)
+                            {
+                                cursor = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec);
+                            }
+                        }
+
+                        guiTextBoxState.cursor = cursor + guiTextBoxState.start;
+
+                        if (guiTextBoxState.select == -1)
+                        {
+                            // Mark start of selection
+                            guiTextBoxState.select = guiTextBoxState.cursor;
+                        }
+
+                        // Move the text when cursor is positioned before or after the text
+                        if ((framesCounter%TEXTBOX_CURSOR_COOLDOWN) == 0 && move)
+                        {
+                            if (cursor == 0) MoveTextBoxCursorLeft(text);
+                            else if (cursor == GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec))
+                            {
+                                MoveTextBoxCursorRight(text, length, textRec);
+                            }
+                        }
+                    }
+                }
+
+                // Calculate X coordinate of the blinking cursor
+                cursorPos.x = GuiTextBoxGetCursorCoordinates(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, guiTextBoxState.cursor - guiTextBoxState.start);
+
+                // Update variables
+                textStartIndex = guiTextBoxState.index;
+
+                if (guiTextBoxState.select == -1)
+                {
+                    selStart = guiTextBoxState.cursor;
+                    selLength = 0;
+                }
+                else if (guiTextBoxState.cursor > guiTextBoxState.select)
+                {
+                    selStart = guiTextBoxState.select;
+                    selLength = guiTextBoxState.cursor - guiTextBoxState.select;
+                }
+                else
+                {
+                    selStart = guiTextBoxState.cursor;
+                    selLength = guiTextBoxState.select - guiTextBoxState.cursor;
+                }
+
+                // We aren't drawing all of the text so make sure `DrawTextRecEx()` is selecting things correctly
+                if (guiTextBoxState.start > selStart)
+                {
+                    selLength -= guiTextBoxState.start - selStart;
+                    selStart = 0;
+                }
+                else selStart = selStart - guiTextBoxState.start;
+            }
+            else state = GUI_STATE_FOCUSED;
+            
+            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(0))) pressed = true;
+        }
+        else
+        {
+            if (active && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C))
+            {
+                // If active copy all text to clipboard even when disabled
+
+                // Backup textbox state
+                int select = guiTextBoxState.select;
+                int cursor = guiTextBoxState.cursor;
+                int start = guiTextBoxState.start;
+
+                if ((guiTextBoxState.select == -1) || (guiTextBoxState.select == guiTextBoxState.cursor))
+                {
+                    // If no selection then mark all text to be copied to clipboard
+                    GuiTextBoxSelectAll(text);
+                }
+
+                GuiTextBoxCopy(text);
+
+                // Restore textbox state
+                guiTextBoxState.select = select;
+                guiTextBoxState.cursor = cursor;
+                guiTextBoxState.start = start;
+            }
+            
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                state = GUI_STATE_FOCUSED;
+                if (IsMouseButtonPressed(0)) pressed = true;
+            }
+
+        }
+        
+        if (pressed) framesCounter = 0;
+    }
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha));
+
+    if (state == GUI_STATE_PRESSED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_FOCUSED)), guiAlpha));
+
+        // Draw blinking cursor
+        if (editMode && active && ((framesCounter/TEXTEDIT_CURSOR_BLINK_FRAMES)%2 == 0) && selLength == 0)
+        {
+            DrawRectangle(cursorPos.x, cursorPos.y, 1, GuiGetStyle(DEFAULT, TEXT_SIZE)*2, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+        }
+    }
+    else if (state == GUI_STATE_DISABLED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
+    }
+
+    // Finally draw the text and selection
+    DrawTextRecEx(guiFont, &text[textStartIndex], textRec, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING), false, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha), selStart, selLength, GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_FG)), GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_BG)));
+
+    return pressed;
+}
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Definition
+//----------------------------------------------------------------------------------
+
+static int GetPrevCodepoint(const char *text, const char *start, int *prev)
+{
+    int c = 0x3f;
+    char *p = (char *)text;
+    *prev = 1;
+
+    for (int i = 0; (p >= start) && (i < 4); p--, i++)
+    {
+        if ((((unsigned char)*p) >> 6) != 2)
+        {
+            c = GetNextCodepoint(p, prev);
+            break;
+        }
+    }
+
+    return c;
+}
+
+// Returns total number of characters(codepoints) in a UTF8 encoded `text` until `\0` or a `\n` is found.
+// NOTE: If a invalid UTF8 sequence is encountered a `?`(0x3f) codepoint is counted instead.
+static inline unsigned int GuiCountCodepointsUntilNewline(const char *text)
+{
+    unsigned int len = 0;
+    char *ptr = (char*)&text[0];
+
+    while ((*ptr != '\0') && (*ptr != '\n'))
+    {
+        int next = 0;
+        int letter = GetNextCodepoint(ptr, &next);
+
+        if (letter == 0x3f) ptr += 1;
+        else ptr += next;
+        ++len;
+    }
+
+    return len;
+}
+
+// Highly synchronized with calculations in DrawTextRecEx()
+static int GuiMeasureTextBox(const char *text, int length, Rectangle rec, int *pos, int mode)
+{
+    // Get gui font properties
+    const Font font = guiFont;
+    const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+    const float spacing = GuiGetStyle(DEFAULT, TEXT_SPACING);
+
+    int textOffsetX = 0;        // Offset between characters
+    float scaleFactor = 0.0f;
+
+    int letter = 0;   // Current character
+    int index = 0;    // Index position in sprite font
+
+    scaleFactor = fontSize/font.baseSize;
+
+    int i = 0, k = 0;
+    int glyphWidth = 0;
+
+    for (i = 0; i < length; i++, k++)
+    {
+        glyphWidth = 0;
+        int next = 1;
+        letter = GetNextCodepoint(&text[i], &next);
+        if (letter == 0x3f) next = 1;
+        index = GetGlyphIndex(font, letter);
+        i += next - 1;
+
+        if (letter != '\n')
+        {
+            glyphWidth = (font.chars[index].advanceX == 0)?
+                         (int)(font.recs[index].width*scaleFactor + spacing):
+                         (int)(font.chars[index].advanceX*scaleFactor + spacing);
+
+            if ((textOffsetX + glyphWidth + 1) >= rec.width) break;
+
+            if ((mode == GUI_MEASURE_MODE_CURSOR_POS) && (*pos == k)) break;
+            else if (mode == GUI_MEASURE_MODE_CURSOR_COORDS)
+            {
+                // Check if the mouse pointer is inside the glyph rect
+                Rectangle grec = {rec.x + textOffsetX - 1, rec.y, glyphWidth, (font.baseSize + font.baseSize/2)*scaleFactor - 1 };
+                Vector2 mouse = GetMousePosition();
+
+                if (CheckCollisionPointRec(mouse, grec))
+                {
+                    // Smooth selection by dividing the glyph rectangle into 2 equal parts and checking where the mouse resides
+                    if (mouse.x > (grec.x + glyphWidth/2))
+                    {
+                        textOffsetX += glyphWidth;
+                        k++;
+                    }
+
+                    break;
+                }
+            }
+        }
+        else break;
+
+        textOffsetX += glyphWidth;
+    }
+
+    *pos = k;
+
+    return (rec.x + textOffsetX - 1);
+}
+
+// Required by GuiTextBoxEx()
+// Highly synchronized with calculations in DrawTextRecEx()
+static int GuiMeasureTextBoxRev(const char *text, int length, Rectangle rec, int *pos)
+{
+    // Get gui font properties
+    const Font font = guiFont;
+    const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+    const float spacing = GuiGetStyle(DEFAULT, TEXT_SPACING);
+
+    int textOffsetX = 0;        // Offset between characters
+    float scaleFactor = 0.0f;
+
+    int letter = 0;   // Current character
+    int index = 0;    // Index position in sprite font
+
+    scaleFactor = fontSize/font.baseSize;
+
+    int i = 0, k = 0;
+    int glyphWidth = 0, prev = 1;
+    for (i = length; i >= 0; i--, k++)
+    {
+        glyphWidth = 0;
+        letter = GetPrevCodepoint(&text[i], &text[0], &prev);
+
+        if (letter == 0x3f) prev = 1;
+        index = GetGlyphIndex(font, letter);
+        i -= prev - 1;
+
+        if (letter != '\n')
+        {
+            glyphWidth = (font.chars[index].advanceX == 0)?
+                         (int)(font.recs[index].width*scaleFactor + spacing):
+                         (int)(font.chars[index].advanceX*scaleFactor + spacing);
+
+            if ((textOffsetX + glyphWidth + 1) >= rec.width) break;
+        }
+        else break;
+
+        textOffsetX += glyphWidth;
+    }
+
+    *pos = k;
+
+    return (i + prev);
+}
+
+// Calculate cursor coordinates based on the cursor position `pos` inside the `text`.
+static inline int GuiTextBoxGetCursorCoordinates(const char *text, int length, Rectangle rec, int pos)
+{
+    return GuiMeasureTextBox(text, length, rec, &pos, GUI_MEASURE_MODE_CURSOR_POS);
+}
+
+// Calculate cursor position in textbox based on mouse coordinates.
+static inline int GuiTextBoxGetCursorFromMouse(const char *text, int length, Rectangle rec, int* pos)
+{
+    return GuiMeasureTextBox(text, length, rec, pos, GUI_MEASURE_MODE_CURSOR_COORDS);
+}
+
+// Calculates how many characters is the textbox able to draw inside rec
+static inline int GuiTextBoxMaxCharacters(const char *text, int length, Rectangle rec)
+{
+    int pos = -1;
+    GuiMeasureTextBox(text, length, rec, &pos, GUI_MEASURE_MODE_CURSOR_END);
+    return pos;
+}
+
+static inline void MoveTextBoxCursorRight(const char* text, int length, Rectangle textRec)
+{
+    // FIXME: Counting codepoints each time we press the key is expensive, find another way
+    int count = GuiCountCodepointsUntilNewline(text);
+    if (guiTextBoxState.cursor < count ) guiTextBoxState.cursor++;
+
+    const int max = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec);
+
+    if ((guiTextBoxState.cursor - guiTextBoxState.start) > max)
+    {
+        const int cidx = GuiTextBoxGetByteIndex(text, guiTextBoxState.index, guiTextBoxState.start, guiTextBoxState.cursor);
+        int pos = 0;
+        guiTextBoxState.index = GuiMeasureTextBoxRev(text, cidx - 1, textRec, &pos);
+        guiTextBoxState.start = guiTextBoxState.cursor - pos;
+    }
+}
+
+static inline void MoveTextBoxCursorLeft(const char* text)
+{
+    if (guiTextBoxState.cursor > 0) guiTextBoxState.cursor--;
+
+    if (guiTextBoxState.cursor < guiTextBoxState.start)
+    {
+        int prev = 0;
+        int letter = GetPrevCodepoint(&text[guiTextBoxState.index - 1], text, &prev);
+        if (letter == 0x3f) prev = 1;
+        guiTextBoxState.start--;
+        guiTextBoxState.index -= prev;
+    }
+}
+
+static int EncodeCodepoint(unsigned int c, char out[5])
+{
+    int len = 0;
+    if (c <= 0x7f)
+    {
+        out[0] = (char)c;
+        len = 1;
+    }
+    else if (c <= 0x7ff)
+    {
+        out[0] = (char)(((c >> 6) & 0x1f) | 0xc0);
+        out[1] = (char)((c & 0x3f) | 0x80);
+        len = 2;
+    }
+    else if (c <= 0xffff)
+    {
+        out[0] = (char)(((c >> 12) & 0x0f) | 0xe0);
+        out[1] = (char)(((c >>  6) & 0x3f) | 0x80);
+        out[2] = (char)((c & 0x3f) | 0x80);
+        len = 3;
+    }
+    else if (c <= 0x10ffff)
+    {
+        out[0] = (char)(((c >> 18) & 0x07) | 0xf0);
+        out[1] = (char)(((c >> 12) & 0x3f) | 0x80);
+        out[2] = (char)(((c >>  6) & 0x3f) | 0x80);
+        out[3] = (char)((c & 0x3f) | 0x80);
+        len = 4;
+    }
+
+    out[len] = 0;
+    return len;
+}
+
+#endif // GUI_TEXTBOX_EXTENDED_IMPLEMENTATION

+ 3701 - 0
gui.mod/raygui/src/raygui.h

@@ -0,0 +1,3701 @@
+/*******************************************************************************************
+*
+*   raygui v2.7-dev - A simple and easy-to-use immediate-mode gui library
+*
+*   DESCRIPTION:
+*
+*   raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
+*   available as a standalone library, as long as input and drawing functions are provided.
+*
+*   Controls provided:
+*
+*   # Container/separators Controls
+*       - WindowBox
+*       - GroupBox
+*       - Line
+*       - Panel
+*
+*   # Basic Controls
+*       - Label
+*       - Button
+*       - LabelButton   --> Label
+*       - ImageButton   --> Button
+*       - ImageButtonEx --> Button
+*       - Toggle
+*       - ToggleGroup   --> Toggle
+*       - CheckBox
+*       - ComboBox
+*       - DropdownBox
+*       - TextBox
+*       - TextBoxMulti
+*       - ValueBox      --> TextBox
+*       - Spinner       --> Button, ValueBox
+*       - Slider
+*       - SliderBar     --> Slider
+*       - ProgressBar
+*       - StatusBar
+*       - ScrollBar
+*       - ScrollPanel
+*       - DummyRec
+*       - Grid
+*
+*   # Advance Controls
+*       - ListView
+*       - ColorPicker   --> ColorPanel, ColorBarHue
+*       - MessageBox    --> Window, Label, Button
+*       - TextInputBox  --> Window, Label, TextBox, Button
+*
+*   It also provides a set of functions for styling the controls based on its properties (size, color).
+*
+*   CONFIGURATION:
+*
+*   #define RAYGUI_IMPLEMENTATION
+*       Generates the implementation of the library into the included file.
+*       If not defined, the library is in header only mode and can be included in other headers
+*       or source files without problems. But only ONE file should hold the implementation.
+*
+*   #define RAYGUI_STATIC (defined by default)
+*       The generated implementation will stay private inside implementation file and all
+*       internal symbols and functions will only be visible inside that file.
+*
+*   #define RAYGUI_STANDALONE
+*       Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
+*       internally in the library and input management and drawing functions must be provided by
+*       the user (check library implementation for further details).
+*
+*   #define RAYGUI_SUPPORT_ICONS
+*       Includes riconsdata.h header defining a set of 128 icons (binary format) to be used on
+*       multiple controls and following raygui styles
+*
+*
+*   VERSIONS HISTORY:
+*       2.6 (09-Sep-2019) ADDED: GuiTextInputBox()
+*                         REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox()
+*                         REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle()
+*                         Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties
+*                         Added 8 new custom styles ready to use
+*                         Multiple minor tweaks and bugs corrected
+*       2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner()
+*       2.3 (29-Apr-2019) Added rIcons auxiliar library and support for it, multiple controls reviewed
+*                         Refactor all controls drawing mechanism to use control state
+*       2.2 (05-Feb-2019) Added GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls
+*       2.1 (26-Dec-2018) Redesign of GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string
+*                         Complete redesign of style system (breaking change)
+*       2.0 (08-Nov-2018) Support controls guiLock and custom fonts, reviewed GuiComboBox(), GuiListView()...
+*       1.9 (09-Oct-2018) Controls review: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()...
+*       1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout
+*       1.5 (21-Jun-2017) Working in an improved styles system
+*       1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones)
+*       1.3 (12-Jun-2017) Redesigned styles system
+*       1.1 (01-Jun-2017) Complete review of the library
+*       1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria.
+*       0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria.
+*       0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria.
+*
+*   CONTRIBUTORS:
+*       Ramon Santamaria:   Supervision, review, redesign, update and maintenance...
+*       Vlad Adrian:        Complete rewrite of GuiTextBox() to support extended features (2019)
+*       Sergio Martinez:    Review, testing (2015) and redesign of multiple controls (2018)
+*       Adria Arranz:       Testing and Implementation of additional controls (2018)
+*       Jordi Jorba:        Testing and Implementation of additional controls (2018)
+*       Albert Martos:      Review and testing of the library (2015)
+*       Ian Eito:           Review and testing of the library (2015)
+*       Kevin Gato:         Initial implementation of basic components (2014)
+*       Daniel Nicolas:     Initial implementation of basic components (2014)
+*
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+*   This software is provided "as-is", without any express or implied warranty. In no event
+*   will the authors be held liable for any damages arising from the use of this software.
+*
+*   Permission is granted to anyone to use this software for any purpose, including commercial
+*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+*     1. The origin of this software must not be misrepresented; you must not claim that you
+*     wrote the original software. If you use this software in a product, an acknowledgment
+*     in the product documentation would be appreciated but is not required.
+*
+*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
+*     as being the original software.
+*
+*     3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef RAYGUI_H
+#define RAYGUI_H
+
+#define RAYGUI_VERSION  "2.6-dev"
+
+#if !defined(RAYGUI_STANDALONE)
+    #include "raylib.h"
+#endif
+
+// Define functions scope to be used internally (static) or externally (extern) to the module including this file
+#if defined(RAYGUI_STATIC)
+    #define RAYGUIDEF static            // Functions just visible to module including this file
+#else
+    #ifdef __cplusplus
+        #define RAYGUIDEF extern "C"    // Functions visible from other files (no name mangling of functions in C++)
+    #else
+        // NOTE: By default any function declared in a C file is extern
+        #define RAYGUIDEF extern        // Functions visible from other files
+    #endif
+#endif
+
+#if defined(_WIN32)
+    #if defined(BUILD_LIBTYPE_SHARED)
+        #define RAYGUIDEF __declspec(dllexport)     // We are building raygui as a Win32 shared library (.dll).
+    #elif defined(USE_LIBTYPE_SHARED)
+        #define RAYGUIDEF __declspec(dllimport)     // We are using raygui as a Win32 shared library (.dll)
+    #endif
+#endif
+
+
+#if !defined(RAYGUI_MALLOC) && !defined(RAYGUI_CALLOC) && !defined(RAYGUI_FREE)
+    #include <stdlib.h>                 // Required for: malloc(), calloc(), free()
+#endif
+
+// Allow custom memory allocators
+#ifndef RAYGUI_MALLOC
+    #define RAYGUI_MALLOC(sz)       malloc(sz)
+#endif
+#ifndef RAYGUI_CALLOC
+    #define RAYGUI_CALLOC(n,sz)     calloc(n,sz)
+#endif
+#ifndef RAYGUI_FREE
+    #define RAYGUI_FREE(p)          free(p)
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define NUM_CONTROLS                    16      // Number of standard controls
+#define NUM_PROPS_DEFAULT               16      // Number of standard properties
+#define NUM_PROPS_EXTENDED               8      // Number of extended properties
+
+#define TEXTEDIT_CURSOR_BLINK_FRAMES    20      // Text edit controls cursor blink timming
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// NOTE: Some types are required for RAYGUI_STANDALONE usage
+//----------------------------------------------------------------------------------
+#if defined(RAYGUI_STANDALONE)
+    #ifndef __cplusplus
+    // Boolean type
+        #ifndef true
+            typedef enum { false, true } bool;
+        #endif
+    #endif
+
+    // Vector2 type
+    typedef struct Vector2 {
+        float x;
+        float y;
+    } Vector2;
+
+    // Vector3 type
+    typedef struct Vector3 {
+        float x;
+        float y;
+        float z;
+    } Vector3;
+
+    // Color type, RGBA (32bit)
+    typedef struct Color {
+        unsigned char r;
+        unsigned char g;
+        unsigned char b;
+        unsigned char a;
+    } Color;
+
+    // Rectangle type
+    typedef struct Rectangle {
+        int x;
+        int y;
+        int width;
+        int height;
+    } Rectangle;
+    
+    // TODO: Texture2D type is very coupled to raylib, mostly required by GuiImageButton()
+    // It should be redesigned to be provided by user
+    typedef struct Texture2D {
+        unsigned int id;        // OpenGL texture id
+        int width;              // Texture base width
+        int height;             // Texture base height
+        int mipmaps;            // Mipmap levels, 1 by default
+        int format;             // Data format (PixelFormat type)
+    } Texture2D;
+
+    // Font character info
+    typedef struct CharInfo CharInfo;
+
+    // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
+    // It should be redesigned to be provided by user
+    typedef struct Font {
+        int baseSize;           // Base size (default chars height)
+        int charsCount;         // Number of characters
+        Texture2D texture;      // Characters texture atlas
+        Rectangle *recs;        // Characters rectangles in texture
+        CharInfo *chars;        // Characters info data
+    } Font;
+#endif
+
+// Style property
+typedef struct GuiStyleProp {
+    unsigned short controlId;
+    unsigned short propertyId;
+    int propertyValue;
+} GuiStyleProp;
+
+// Gui control state
+typedef enum {
+    GUI_STATE_NORMAL = 0,
+    GUI_STATE_FOCUSED,
+    GUI_STATE_PRESSED,
+    GUI_STATE_DISABLED,
+} GuiControlState;
+
+// Gui control text alignment
+typedef enum {
+    GUI_TEXT_ALIGN_LEFT = 0,
+    GUI_TEXT_ALIGN_CENTER,
+    GUI_TEXT_ALIGN_RIGHT,
+} GuiTextAlignment;
+
+// Gui controls
+typedef enum {
+    DEFAULT = 0,
+    LABEL,          // LABELBUTTON
+    BUTTON,         // IMAGEBUTTON
+    TOGGLE,         // TOGGLEGROUP
+    SLIDER,         // SLIDERBAR
+    PROGRESSBAR,
+    CHECKBOX,
+    COMBOBOX,
+    DROPDOWNBOX,
+    TEXTBOX,        // TEXTBOXMULTI
+    VALUEBOX,
+    SPINNER,
+    LISTVIEW,
+    COLORPICKER,
+    SCROLLBAR,
+    STATUSBAR
+} GuiControl;
+
+// Gui base properties for every control
+typedef enum {
+    BORDER_COLOR_NORMAL = 0,
+    BASE_COLOR_NORMAL,
+    TEXT_COLOR_NORMAL,
+    BORDER_COLOR_FOCUSED,
+    BASE_COLOR_FOCUSED,
+    TEXT_COLOR_FOCUSED,
+    BORDER_COLOR_PRESSED,
+    BASE_COLOR_PRESSED,
+    TEXT_COLOR_PRESSED,
+    BORDER_COLOR_DISABLED,
+    BASE_COLOR_DISABLED,
+    TEXT_COLOR_DISABLED,
+    BORDER_WIDTH,
+    TEXT_PADDING,
+    TEXT_ALIGNMENT,
+    RESERVED
+} GuiControlProperty;
+
+// Gui extended properties depend on control
+// NOTE: We reserve a fixed size of additional properties per control
+
+// DEFAULT properties
+typedef enum {
+    TEXT_SIZE = 16,
+    TEXT_SPACING,
+    LINE_COLOR,
+    BACKGROUND_COLOR,
+} GuiDefaultProperty;
+
+// Label
+//typedef enum { } GuiLabelProperty;
+
+// Button
+//typedef enum { } GuiButtonProperty;
+
+// Toggle / ToggleGroup
+typedef enum {
+    GROUP_PADDING = 16,
+} GuiToggleProperty;
+
+// Slider / SliderBar
+typedef enum {
+    SLIDER_WIDTH = 16,
+    SLIDER_PADDING
+} GuiSliderProperty;
+
+// ProgressBar
+typedef enum {
+    PROGRESS_PADDING = 16,
+} GuiProgressBarProperty;
+
+// CheckBox
+typedef enum {
+    CHECK_PADDING = 16
+} GuiCheckBoxProperty;
+
+// ComboBox
+typedef enum {
+    COMBO_BUTTON_WIDTH = 16,
+    COMBO_BUTTON_PADDING
+} GuiComboBoxProperty;
+
+// DropdownBox
+typedef enum {
+    ARROW_PADDING = 16,
+    DROPDOWN_ITEMS_PADDING
+} GuiDropdownBoxProperty;
+
+// TextBox / TextBoxMulti / ValueBox / Spinner
+typedef enum {
+    TEXT_INNER_PADDING = 16,
+    TEXT_LINES_PADDING,
+    COLOR_SELECTED_FG,
+    COLOR_SELECTED_BG
+} GuiTextBoxProperty;
+
+// Spinner
+typedef enum {
+    SPIN_BUTTON_WIDTH = 16,
+    SPIN_BUTTON_PADDING,
+} GuiSpinnerProperty;
+
+// ScrollBar
+typedef enum {
+    ARROWS_SIZE = 16,
+    ARROWS_VISIBLE,
+    SCROLL_SLIDER_PADDING,
+    SCROLL_SLIDER_SIZE,
+    SCROLL_PADDING,
+    SCROLL_SPEED,
+} GuiScrollBarProperty;
+
+// ScrollBar side
+typedef enum {
+    SCROLLBAR_LEFT_SIDE = 0,
+    SCROLLBAR_RIGHT_SIDE
+} GuiScrollBarSide;
+
+// ListView
+typedef enum {
+    LIST_ITEMS_HEIGHT = 16,
+    LIST_ITEMS_PADDING,
+    SCROLLBAR_WIDTH,
+    SCROLLBAR_SIDE,
+} GuiListViewProperty;
+
+// ColorPicker
+typedef enum {
+    COLOR_SELECTOR_SIZE = 16,
+    HUEBAR_WIDTH,                  // Right hue bar width
+    HUEBAR_PADDING,                // Right hue bar separation from panel
+    HUEBAR_SELECTOR_HEIGHT,        // Right hue bar selector height
+    HUEBAR_SELECTOR_OVERFLOW       // Right hue bar selector overflow
+} GuiColorPickerProperty;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+
+// Global gui modification functions
+RAYGUIDEF void GuiEnable(void);                                         // Enable gui controls (global state)
+RAYGUIDEF void GuiDisable(void);                                        // Disable gui controls (global state)
+RAYGUIDEF void GuiLock(void);                                           // Lock gui controls (global state)
+RAYGUIDEF void GuiUnlock(void);                                         // Unlock gui controls (global state)
+RAYGUIDEF void GuiFade(float alpha);                                    // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
+
+RAYGUIDEF void GuiSetState(int state);                                  // Set gui state (global state)
+RAYGUIDEF int GuiGetState(void);                                        // Get gui state (global state)
+
+RAYGUIDEF void GuiSetFont(Font font);                                   // Set gui custom font (global state)
+RAYGUIDEF Font GuiGetFont(void);                                        // Get gui custom font (global state)
+
+// Style set/get functions
+RAYGUIDEF void GuiSetStyle(int control, int property, int value);       // Set one style property
+RAYGUIDEF int GuiGetStyle(int control, int property);                   // Get one style property
+
+// Container/separator controls, useful for controls organization
+RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *title);                                       // Window Box control, shows a window that can be closed
+RAYGUIDEF void GuiGroupBox(Rectangle bounds, const char *text);                                         // Group Box control with text name
+RAYGUIDEF void GuiLine(Rectangle bounds, const char *text);                                             // Line separator control, could contain text
+RAYGUIDEF void GuiPanel(Rectangle bounds);                                                              // Panel control, useful to group controls
+RAYGUIDEF Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 *scroll);               // Scroll Panel control
+
+// Basic controls set
+RAYGUIDEF void GuiLabel(Rectangle bounds, const char *text);                                            // Label control, shows text
+RAYGUIDEF bool GuiButton(Rectangle bounds, const char *text);                                           // Button control, returns true when clicked
+RAYGUIDEF bool GuiLabelButton(Rectangle bounds, const char *text);                                      // Label button control, show true when clicked
+RAYGUIDEF bool GuiImageButton(Rectangle bounds, const char *text, Texture2D texture);                   // Image button control, returns true when clicked
+RAYGUIDEF bool GuiImageButtonEx(Rectangle bounds, const char *text, Texture2D texture, Rectangle texSource);    // Image button extended control, returns true when clicked
+RAYGUIDEF bool GuiToggle(Rectangle bounds, const char *text, bool active);                              // Toggle Button control, returns true when active
+RAYGUIDEF int GuiToggleGroup(Rectangle bounds, const char *text, int active);                           // Toggle Group control, returns active toggle index
+RAYGUIDEF bool GuiCheckBox(Rectangle bounds, const char *text, bool checked);                           // Check Box control, returns true when active
+RAYGUIDEF int GuiComboBox(Rectangle bounds, const char *text, int active);                              // Combo Box control, returns selected item index
+RAYGUIDEF bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode);          // Dropdown Box control, returns selected item
+RAYGUIDEF bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);     // Spinner control, returns selected value
+RAYGUIDEF bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);    // Value Box control, updates input text with numbers
+RAYGUIDEF bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode);                   // Text Box control, updates input text
+RAYGUIDEF bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode);              // Text Box control with multiple lines
+RAYGUIDEF float GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);       // Slider control, returns selected value
+RAYGUIDEF float GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);    // Slider Bar control, returns selected value
+RAYGUIDEF float GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);  // Progress Bar control, shows current progress value
+RAYGUIDEF void GuiStatusBar(Rectangle bounds, const char *text);                                        // Status Bar control, shows info text
+RAYGUIDEF void GuiDummyRec(Rectangle bounds, const char *text);                                         // Dummy control for placeholders
+RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue);                    // Scroll Bar control
+RAYGUIDEF Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs);                                // Grid control
+
+// Advance controls set
+RAYGUIDEF int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active);            // List View control, returns selected list item index
+RAYGUIDEF int GuiListViewEx(Rectangle bounds, const char **text, int count, int *focus, int *scrollIndex, int active);      // List View with extended parameters
+RAYGUIDEF int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons);                 // Message Box control, displays a message
+RAYGUIDEF int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text);   // Text Input Box control, ask for text
+RAYGUIDEF Color GuiColorPicker(Rectangle bounds, Color color);                                          // Color Picker control
+
+// Styles loading functions
+RAYGUIDEF void GuiLoadStyle(const char *fileName);              // Load style file (.rgs)
+RAYGUIDEF void GuiLoadStyleDefault(void);                       // Load style default over global style
+
+/*
+typedef GuiStyle (unsigned int *)
+RAYGUIDEF GuiStyle LoadGuiStyle(const char *fileName);          // Load style from file (.rgs)
+RAYGUIDEF void UnloadGuiStyle(GuiStyle style);                  // Unload style
+*/
+
+RAYGUIDEF const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported)
+
+#if defined(RAYGUI_SUPPORT_ICONS)
+// Gui icons functionality
+RAYGUIDEF void GuiDrawIcon(int iconId, Vector2 position, int pixelSize, Color color);
+
+RAYGUIDEF unsigned int *GuiGetIcons(void);                      // Get full icons data pointer
+RAYGUIDEF unsigned int *GuiGetIconData(int iconId);             // Get icon bit data
+RAYGUIDEF void GuiSetIconData(int iconId, unsigned int *data);  // Set icon bit data
+
+RAYGUIDEF void GuiSetIconPixel(int iconId, int x, int y);       // Set icon pixel value
+RAYGUIDEF void GuiClearIconPixel(int iconId, int x, int y);     // Clear icon pixel value
+RAYGUIDEF bool GuiCheckIconPixel(int iconId, int x, int y);     // Check icon pixel value
+#endif
+
+#endif // RAYGUI_H
+
+
+/***********************************************************************************
+*
+*   RAYGUI IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(RAYGUI_IMPLEMENTATION)
+
+#if defined(RAYGUI_SUPPORT_ICONS)
+    #define RICONS_IMPLEMENTATION
+    #include "ricons.h"         // Required for: raygui icons data
+#endif
+
+#include <stdio.h>              // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf()
+#include <string.h>             // Required for: strlen() on GuiTextBox()
+
+#if defined(RAYGUI_STANDALONE)
+    #include <stdarg.h>         // Required for: va_list, va_start(), vfprintf(), va_end()
+#endif
+
+#ifdef __cplusplus
+    #define RAYGUI_CLITERAL(name) name
+#else
+    #define RAYGUI_CLITERAL(name) (name)
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Gui control property style color element
+typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static GuiControlState guiState = GUI_STATE_NORMAL;
+
+static Font guiFont = { 0 };            // NOTE: Highly coupled to raylib
+static bool guiLocked = false;
+static float guiAlpha = 1.0f;
+
+// Global gui style array (allocated on heap by default)
+// NOTE: In raygui we manage a single int array with all the possible style properties.
+// When a new style is loaded, it loads over the global style... but default gui style
+// could always be recovered with GuiLoadStyleDefault()
+static unsigned int guiStyle[NUM_CONTROLS*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED)] = { 0 };
+static bool guiStyleLoaded = false;
+
+//----------------------------------------------------------------------------------
+// Standalone Mode Functions Declaration
+//
+// NOTE: raygui depend on some raylib input and drawing functions
+// To use raygui as standalone library, below functions must be defined by the user
+//----------------------------------------------------------------------------------
+#if defined(RAYGUI_STANDALONE)
+
+#define KEY_RIGHT           262
+#define KEY_LEFT            263
+#define KEY_DOWN            264
+#define KEY_UP              265
+#define KEY_BACKSPACE       259
+#define KEY_ENTER           257
+#define MOUSE_LEFT_BUTTON     0
+
+// Input required functions
+//-------------------------------------------------------------------------------
+static Vector2 GetMousePosition(void);
+static int GetMouseWheelMove(void);
+static bool IsMouseButtonDown(int button);
+static bool IsMouseButtonPressed(int button);
+static bool IsMouseButtonReleased(int button);
+
+static bool IsKeyDown(int key);
+static bool IsKeyPressed(int key);
+static int GetKeyPressed(void);         // -- GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()
+//-------------------------------------------------------------------------------
+
+// Drawing required functions
+//-------------------------------------------------------------------------------
+static void DrawRectangle(int x, int y, int width, int height, Color color);
+static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4);     // -- GuiColorPicker()
+static void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                              // -- GuiDropdownBox(), GuiScrollBar()
+static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);       // -- GuiImageButtonEx()
+
+static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // -- GuiTextBoxMulti()
+//-------------------------------------------------------------------------------
+
+// Text required functions
+//-------------------------------------------------------------------------------
+static Font GetFontDefault(void);   // -- GuiLoadStyleDefault()
+static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing);                          // -- GetTextWidth(), GuiTextBoxMulti()
+static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint);  // -- GuiDrawText()
+
+static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount);  // -- GuiLoadStyle()
+static char *LoadText(const char *fileName); // -- GuiLoadStyle()
+static const char *GetDirectoryPath(const char *filePath);  // -- GuiLoadStyle()
+//-------------------------------------------------------------------------------
+
+// raylib functions already implemented in raygui
+//-------------------------------------------------------------------------------
+static Color GetColor(int hexValue);                // Returns a Color struct from hexadecimal value
+static int ColorToInt(Color color);                 // Returns hexadecimal value for a Color
+static Color Fade(Color color, float alpha);        // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec);   // Check if point is inside rectangle
+static const char *TextFormat(const char *text, ...);               // Formatting of text with variables to 'embed'
+static const char **TextSplit(const char *text, char delimiter, int *count);    // Split text into multiple strings
+static int TextToInteger(const char *text);         // Get integer value from text
+
+static void DrawRectangleRec(Rectangle rec, Color color);   // Draw rectangle filled with color
+static void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color);    // Draw rectangle outlines
+static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);  // Draw rectangle vertical gradient
+//-------------------------------------------------------------------------------
+
+#endif      // RAYGUI_STANDALONE
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Declaration
+//----------------------------------------------------------------------------------
+static Vector3 ConvertHSVtoRGB(Vector3 hsv);    // Convert color data from HSV to RGB
+static Vector3 ConvertRGBtoHSV(Vector3 rgb);    // Convert color data from RGB to HSV
+
+// Gui get text width using default font
+static int GetTextWidth(const char *text)       // TODO: GetTextSize()
+{
+    Vector2 size = { 0 };
+
+    if ((text != NULL) && (text[0] != '\0')) size = MeasureTextEx(guiFont, text, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING));
+
+    // TODO: Consider text icon width here???
+
+    return (int)size.x;
+}
+
+// Get text bounds considering control bounds
+static Rectangle GetTextBounds(int control, Rectangle bounds)
+{
+    Rectangle textBounds = bounds;
+
+    textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
+    textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH);
+    textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH);
+    textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH);
+
+    // Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT
+    switch (control)
+    {
+        case COMBOBOX: bounds.width -= (GuiGetStyle(control, COMBO_BUTTON_WIDTH) + GuiGetStyle(control, COMBO_BUTTON_PADDING)); break;
+        case VALUEBOX: break;   // NOTE: ValueBox text value always centered, text padding applies to label
+        default:
+        {
+            if (GuiGetStyle(control, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING);
+            else textBounds.x += GuiGetStyle(control, TEXT_PADDING);
+        } break;
+    }
+
+    // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW (scrollbar?)
+    // More special cases (label side): CHECKBOX, SLIDER, VALUEBOX, SPINNER
+
+    return textBounds;
+}
+
+// Get text icon if provided and move text cursor
+// NOTE: We support up to 999 values for iconId
+static const char *GetTextIcon(const char *text, int *iconId)
+{
+#if defined(RAYGUI_SUPPORT_ICONS)
+    *iconId = -1;
+    if (text[0] == '#')     // Maybe we have an icon!
+    {
+        char iconValue[4] = { 0 };  // Maximum length for icon value: 3 digits + '\0'
+
+        int pos = 1;
+        while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9'))
+        {
+            iconValue[pos - 1] = text[pos];
+            pos++;
+        }
+        
+        if (text[pos] == '#')
+        {
+            *iconId = TextToInteger(iconValue);
+
+            // Move text pointer after icon
+            // WARNING: If only icon provided, it could point to EOL character!
+            if (*iconId >= 0) text += (pos + 1);
+        }
+    }
+#endif
+
+    return text;
+}
+
+// Gui draw text using default font
+static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color tint)
+{
+    #define TEXT_VALIGN_PIXEL_OFFSET(h)  ((int)h%2)     // Vertical alignment for pixel perfect
+
+    if ((text != NULL) && (text[0] != '\0'))
+    {
+        int iconId = 0;
+        text = GetTextIcon(text, &iconId);  // Check text for icon and move cursor
+
+        // Get text position depending on alignment and iconId
+        //---------------------------------------------------------------------------------
+        #define ICON_TEXT_PADDING   4
+
+        Vector2 position = { bounds.x, bounds.y };
+
+        // NOTE: We get text size after icon been processed
+        int textWidth = GetTextWidth(text);
+        int textHeight = GuiGetStyle(DEFAULT, TEXT_SIZE);
+
+#if defined(RAYGUI_SUPPORT_ICONS)
+        if (iconId >= 0)
+        {
+            textWidth += RICON_SIZE;
+
+            // WARNING: If only icon provided, text could be pointing to eof character!
+            if ((text != NULL) && (text[0] != '\0')) textWidth += ICON_TEXT_PADDING;
+        }
+#endif
+        // Check guiTextAlign global variables
+        switch (alignment)
+        {
+            case GUI_TEXT_ALIGN_LEFT:
+            {
+                position.x = bounds.x;
+                position.y = bounds.y + bounds.height/2 - textHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
+            } break;
+            case GUI_TEXT_ALIGN_CENTER:
+            {
+                position.x = bounds.x + bounds.width/2 - textWidth/2;
+                position.y = bounds.y + bounds.height/2 - textHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
+            } break;
+            case GUI_TEXT_ALIGN_RIGHT:
+            {
+                position.x = bounds.x + bounds.width - textWidth;
+                position.y = bounds.y + bounds.height/2 - textHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
+            } break;
+            default: break;
+        }
+
+        // NOTE: Make sure we get pixel-perfect coordinates,
+        // In case of decimals we got weird text positioning
+        position.x = (float)((int)position.x);
+        position.y = (float)((int)position.y);
+        //---------------------------------------------------------------------------------
+
+        // Draw text (with icon if available)
+        //---------------------------------------------------------------------------------
+#if defined(RAYGUI_SUPPORT_ICONS)
+        if (iconId >= 0)
+        {
+            // NOTE: We consider icon height, probably different than text size
+            GuiDrawIcon(iconId, RAYGUI_CLITERAL(Vector2){ position.x, bounds.y + bounds.height/2 - RICON_SIZE/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height) }, 1, tint);
+            position.x += (RICON_SIZE + ICON_TEXT_PADDING);
+        }
+#endif
+        DrawTextEx(guiFont, text, position, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING), tint);
+        //---------------------------------------------------------------------------------
+    }
+}
+
+// Split controls text into multiple strings
+// Also check for multiple columns (required by GuiToggleGroup())
+static const char **GuiTextSplit(const char *text, int *count, int *textRow);
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Enable gui global state
+void GuiEnable(void) { guiState = GUI_STATE_NORMAL; }
+
+// Disable gui global state
+void GuiDisable(void) { guiState = GUI_STATE_DISABLED; }
+
+// Lock gui global state
+void GuiLock(void) { guiLocked = true; }
+
+// Unlock gui global state
+void GuiUnlock(void) { guiLocked = false; }
+
+// Set gui controls alpha global state
+void GuiFade(float alpha)
+{
+    if (alpha < 0.0f) alpha = 0.0f;
+    else if (alpha > 1.0f) alpha = 1.0f;
+
+    guiAlpha = alpha;
+}
+
+// Set gui state (global state)
+void GuiSetState(int state) { guiState = (GuiControlState)state; }
+
+// Get gui state (global state)
+int GuiGetState(void) { return guiState; }
+
+// Set custom gui font
+// NOTE: Font loading/unloading is external to raygui
+void GuiSetFont(Font font)
+{
+    if (font.texture.id > 0)
+    {
+        // NOTE: If we try to setup a font but default style has not been
+        // lazily loaded before, it will be overwritten, so we need to force
+        // default style loading first
+        if (!guiStyleLoaded) GuiLoadStyleDefault();
+
+        guiFont = font;
+        GuiSetStyle(DEFAULT, TEXT_SIZE, font.baseSize);
+    }
+}
+
+// Get custom gui font
+Font GuiGetFont(void)
+{
+    return guiFont;
+}
+
+// Set control style property value
+void GuiSetStyle(int control, int property, int value)
+{
+    if (!guiStyleLoaded) GuiLoadStyleDefault();
+    guiStyle[control*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED) + property] = value;
+
+    // Default properties are propagated to all controls
+    if ((control == 0) && (property < NUM_PROPS_DEFAULT))
+    {
+        for (int i = 1; i < NUM_CONTROLS; i++) guiStyle[i*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED) + property] = value;
+    }
+}
+
+// Get control style property value
+int GuiGetStyle(int control, int property)
+{
+    if (!guiStyleLoaded) GuiLoadStyleDefault();
+    return guiStyle[control*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED) + property];
+}
+
+// Window Box control
+bool GuiWindowBox(Rectangle bounds, const char *title)
+{
+    // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
+    #define WINDOW_STATUSBAR_HEIGHT        22
+
+    GuiControlState state = guiState;
+    bool clicked = false;
+
+    int statusBarHeight = WINDOW_STATUSBAR_HEIGHT + 2*GuiGetStyle(STATUSBAR, BORDER_WIDTH);
+    statusBarHeight += (statusBarHeight%2);
+
+    Rectangle statusBar = { bounds.x, bounds.y, bounds.width, statusBarHeight };
+    if (bounds.height < statusBarHeight*2) bounds.height = statusBarHeight*2;
+
+    Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20,
+                                 statusBar.y + statusBarHeight/2 - 18/2, 18, 18 };
+
+    // Update control
+    //--------------------------------------------------------------------
+    // NOTE: Logic is directly managed by button
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+
+    // Draw window base
+    DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DEFAULT, BORDER + (state*3))), guiAlpha));
+    DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH),
+                                  bounds.width - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2, bounds.height - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2 },
+                                  Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha));
+
+    // Draw window header as status bar
+    GuiStatusBar(statusBar, title);
+
+    // Draw window close button
+    int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+    int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+#if defined(RAYGUI_SUPPORT_ICONS)
+    clicked = GuiButton(closeButtonRec, GuiIconText(RICON_CROSS_SMALL, NULL));
+#else
+    clicked = GuiButton(closeButtonRec, "x");
+#endif
+    GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
+    //--------------------------------------------------------------------
+
+    return clicked;
+}
+
+// Group Box control with text name
+void GuiGroupBox(Rectangle bounds, const char *text)
+{
+    #define GROUPBOX_LINE_THICK     1
+    #define GROUPBOX_TEXT_PADDING  10
+
+    GuiControlState state = guiState;
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangle(bounds.x, bounds.y, GROUPBOX_LINE_THICK, bounds.height, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
+    DrawRectangle(bounds.x, bounds.y + bounds.height - 1, bounds.width, GROUPBOX_LINE_THICK, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
+    DrawRectangle(bounds.x + bounds.width - 1, bounds.y, GROUPBOX_LINE_THICK, bounds.height, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
+
+    GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, 1 }, text);
+    //--------------------------------------------------------------------
+}
+
+// Line control
+void GuiLine(Rectangle bounds, const char *text)
+{
+    #define LINE_TEXT_PADDING  10
+
+    GuiControlState state = guiState;
+
+    Color color = Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha);
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (text == NULL) DrawRectangle(bounds.x, bounds.y + bounds.height/2, bounds.width, 1, color);
+    else
+    {
+        Rectangle textBounds = { 0 };
+        textBounds.width = GetTextWidth(text);      // TODO: Consider text icon
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + LINE_TEXT_PADDING;
+        textBounds.y = bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+        // Draw line with embedded text label: "--- text --------------"
+        DrawRectangle(bounds.x, bounds.y, LINE_TEXT_PADDING - 2, 1, color);
+        GuiLabel(textBounds, text);
+        DrawRectangle(bounds.x + LINE_TEXT_PADDING + textBounds.width + 4, bounds.y, bounds.width - textBounds.width - LINE_TEXT_PADDING - 4, 1, color);
+    }
+    //--------------------------------------------------------------------
+}
+
+// Panel control
+void GuiPanel(Rectangle bounds)
+{
+    #define PANEL_BORDER_WIDTH   1
+
+    GuiControlState state = guiState;
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)), guiAlpha));
+    DrawRectangleLinesEx(bounds, PANEL_BORDER_WIDTH, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)), guiAlpha));
+    //--------------------------------------------------------------------
+}
+
+// Scroll Panel control
+Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 *scroll)
+{
+    GuiControlState state = guiState;
+
+    Vector2 scrollPos = { 0.0f, 0.0f };
+    if (scroll != NULL) scrollPos = *scroll;
+
+    bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
+    bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
+
+    // Recheck to account for the other scrollbar being visible
+    if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
+    if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
+
+    const int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
+    const int verticalScrollBarWidth =  hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
+    const 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 };
+    const 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) };
+
+    // Calculate view area (area without the scrollbars)
+    Rectangle view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
+                RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } :
+                RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth };
+
+    // Clip view area to the actual content size
+    if (view.width > content.width) view.width = content.width;
+    if (view.height > content.height) view.height = content.height;
+
+    // TODO: Review!
+    const int horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? -verticalScrollBarWidth : 0) - GuiGetStyle(DEFAULT, BORDER_WIDTH) : ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? -verticalScrollBarWidth : 0) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    const int horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? verticalScrollBarWidth : 0) : -GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    const int verticalMin = hasVerticalScrollBar? -GuiGetStyle(DEFAULT, BORDER_WIDTH) : -GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    const int verticalMax = hasVerticalScrollBar? content.height - bounds.height + horizontalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) : -GuiGetStyle(DEFAULT, BORDER_WIDTH);
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check button state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+
+            if (hasHorizontalScrollBar)
+            {
+                if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+                if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+            }
+
+            if (hasVerticalScrollBar)
+            {
+                if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+                if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+            }
+
+            scrollPos.y += GetMouseWheelMove()*20;
+        }
+    }
+
+    // Normalize scroll values
+    if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin;
+    if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax;
+    if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin;
+    if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax;
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));        // Draw background
+
+    // Save size of the scrollbar slider
+    const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+
+    // Draw horizontal scrollbar if visible
+    if (hasHorizontalScrollBar)
+    {
+        // Change scrollbar slider size to show the diff in size between the content width and the widget width
+        GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, ((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/content.width)*(bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth));
+        scrollPos.x = -GuiScrollBar(horizontalScrollBar, -scrollPos.x, horizontalMin, horizontalMax);
+    }
+
+    // Draw vertical scrollbar if visible
+    if (hasVerticalScrollBar)
+    {
+        // Change scrollbar slider size to show the diff in size between the content height and the widget height
+        GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, ((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/content.height)* (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth));
+        scrollPos.y = -GuiScrollBar(verticalScrollBar, -scrollPos.y, verticalMin, verticalMax);
+    }
+
+    // Draw detail corner rectangle if both scroll bars are visible
+    if (hasHorizontalScrollBar && hasVerticalScrollBar)
+    {
+        // TODO: Consider scroll bars side
+        DrawRectangle(horizontalScrollBar.x + horizontalScrollBar.width + 2,
+                      verticalScrollBar.y + verticalScrollBar.height + 2,
+                      horizontalScrollBarWidth - 4, verticalScrollBarWidth - 4,
+                      Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))), guiAlpha));
+    }
+
+    // Set scrollbar slider size back to the way it was before
+    GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
+
+    // Draw scrollbar lines depending on current state
+    DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, (float)BORDER + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    if (scroll != NULL) *scroll = scrollPos;
+
+    return view;
+}
+
+// Label control
+void GuiLabel(Rectangle bounds, const char *text)
+{
+    GuiControlState state = guiState;
+
+    // Update control
+    //--------------------------------------------------------------------
+    // ...
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, (state == GUI_STATE_DISABLED)? TEXT_COLOR_DISABLED : TEXT_COLOR_NORMAL)), guiAlpha));
+    //--------------------------------------------------------------------
+}
+
+// Button control, returns true when clicked
+bool GuiButton(Rectangle bounds, const char *text)
+{
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check button state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+
+            if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha));
+    DrawRectangle(bounds.x + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.y + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
+
+    GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
+    //------------------------------------------------------------------
+
+    return pressed;
+}
+
+// Label button control
+bool GuiLabelButton(Rectangle bounds, const char *text)
+{
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    // NOTE: We force bounds.width to be all text
+    int textWidth = MeasureTextEx(guiFont, text, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING)).x;
+    if (bounds.width < textWidth) bounds.width = textWidth;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check checkbox state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+
+            if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return pressed;
+}
+
+// Image button control, returns true when clicked
+bool GuiImageButton(Rectangle bounds, const char *text, Texture2D texture)
+{
+    return GuiImageButtonEx(bounds, text, texture, RAYGUI_CLITERAL(Rectangle){ 0, 0, (float)texture.width, (float)texture.height });
+}
+
+// Image button control, returns true when clicked
+bool GuiImageButtonEx(Rectangle bounds, const char *text, Texture2D texture, Rectangle texSource)
+{
+    GuiControlState state = guiState;
+    bool clicked = false;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check button state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) clicked = true;
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha));
+    DrawRectangle(bounds.x + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.y + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
+
+    if (text != NULL) GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
+    if (texture.id > 0) DrawTextureRec(texture, texSource, RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width/2 - texSource.width/2, bounds.y + bounds.height/2 - texSource.height/2 }, Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
+    //------------------------------------------------------------------
+
+    return clicked;
+}
+
+// Toggle Button control, returns true when active
+bool GuiToggle(Rectangle bounds, const char *text, bool active)
+{
+    GuiControlState state = guiState;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check toggle button state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+            {
+                state = GUI_STATE_NORMAL;
+                active = !active;
+            }
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (state == GUI_STATE_NORMAL)
+    {
+        DrawRectangleLinesEx(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, (active? BORDER_COLOR_PRESSED : (BORDER + state*3)))), guiAlpha));
+        DrawRectangle(bounds.x + GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.y + GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, (active? BASE_COLOR_PRESSED : (BASE + state*3)))), guiAlpha));
+
+        GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, (active? TEXT_COLOR_PRESSED : (TEXT + state*3)))), guiAlpha));
+    }
+    else
+    {
+        DrawRectangleLinesEx(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), guiAlpha));
+        DrawRectangle(bounds.x + GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.y + GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TOGGLE, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, BASE + state*3)), guiAlpha));
+
+        GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)), guiAlpha));
+    }
+    //--------------------------------------------------------------------
+
+    return active;
+}
+
+// Toggle Group control, returns toggled button index
+int GuiToggleGroup(Rectangle bounds, const char *text, int active)
+{
+    #if !defined(TOGGLEGROUP_MAX_ELEMENTS)
+        #define TOGGLEGROUP_MAX_ELEMENTS    32
+    #endif
+
+    float initBoundsX = bounds.x;
+
+    // Get substrings items from text (items pointers)
+    int rows[TOGGLEGROUP_MAX_ELEMENTS] = { 0 };
+    int itemsCount = 0;
+    const char **items = GuiTextSplit(text, &itemsCount, rows);
+
+    int prevRow = rows[0];
+
+    for (int i = 0; i < itemsCount; i++)
+    {
+        if (prevRow != rows[i])
+        {
+            bounds.x = initBoundsX;
+            bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING));
+            prevRow = rows[i];
+        }
+
+        if (i == active) GuiToggle(bounds, items[i], true);
+        else if (GuiToggle(bounds, items[i], false) == true) active = i;
+
+        bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING));
+    }
+
+    return active;
+}
+
+// Check Box control, returns true when active
+bool GuiCheckBox(Rectangle bounds, const char *text, bool checked)
+{
+    GuiControlState state = guiState;
+
+    Rectangle textBounds = { 0 };
+
+    if (text != NULL)
+    {
+        textBounds.width = GetTextWidth(text);
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+        if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING);
+    }
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        Rectangle totalBounds = {
+            (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT)? textBounds.x : bounds.x,
+            bounds.y,
+            bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING),
+            bounds.height,
+        };
+
+        // Check checkbox state
+        if (CheckCollisionPointRec(mousePoint, totalBounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+
+            if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) checked = !checked;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), guiAlpha));
+    if (checked) DrawRectangle(bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
+                               bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
+                               bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
+                               bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
+                               Fade(GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)), guiAlpha));
+
+    if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return checked;
+}
+
+// Combo Box control, returns selected item index
+int GuiComboBox(Rectangle bounds, const char *text, int active)
+{
+    GuiControlState state = guiState;
+
+    bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_PADDING));
+
+    Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_PADDING),
+                           (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
+
+    // Get substrings items from text (items pointers, lengths and count)
+    int itemsCount = 0;
+    const char **items = GuiTextSplit(text, &itemsCount, NULL);
+
+    if (active < 0) active = 0;
+    else if (active > itemsCount - 1) active = itemsCount - 1;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemsCount > 1))
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds) ||
+            CheckCollisionPointRec(mousePoint, selector))
+        {
+            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+            {
+                active += 1;
+                if (active >= itemsCount) active = 0;
+            }
+
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    // Draw combo box main
+    DrawRectangleLinesEx(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), guiAlpha));
+    DrawRectangle(bounds.x + GuiGetStyle(COMBOBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(COMBOBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(COMBOBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(COMBOBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))), guiAlpha));
+
+    GuiDrawText(items[active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))), guiAlpha));
+
+    // Draw selector using a custom button
+    // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
+    int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+    int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+
+    GuiButton(selector, TextFormat("%i/%i", active + 1, itemsCount));
+
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+    //--------------------------------------------------------------------
+
+    return active;
+}
+
+// Dropdown Box control
+// NOTE: Returns mouse click
+bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode)
+{
+    GuiControlState state = guiState;
+    int itemSelected = *active;
+    int itemFocused = -1;
+
+    // Get substrings items from text (items pointers, lengths and count)
+    int itemsCount = 0;
+    const char **items = GuiTextSplit(text, &itemsCount, NULL);
+
+    Rectangle boundsOpen = bounds;
+    boundsOpen.height = (itemsCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
+
+    Rectangle itemBounds = bounds;
+
+    bool pressed = false;       // Check mouse button pressed
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemsCount > 1))
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (editMode)
+        {
+            state = GUI_STATE_PRESSED;
+
+            // Check if mouse has been pressed or released outside limits
+            if (!CheckCollisionPointRec(mousePoint, boundsOpen))
+            {
+                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
+            }
+
+            // Check if already selected item has been pressed again
+            if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
+
+            // Check focused and selected item
+            for (int i = 0; i < itemsCount; i++)
+            {
+                // Update item rectangle y position for next item
+                itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
+
+                if (CheckCollisionPointRec(mousePoint, itemBounds))
+                {
+                    itemFocused = i;
+                    if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+                    {
+                        itemSelected = i;
+                        pressed = true;     // Item selected, change to editMode = false
+                    }
+                    break;
+                }
+            }
+
+            itemBounds = bounds;
+        }
+        else
+        {
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+                {
+                    pressed = true;
+                    state = GUI_STATE_PRESSED;
+                }
+                else state = GUI_STATE_FOCUSED;
+            }
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (editMode) GuiPanel(boundsOpen);
+
+    DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)), guiAlpha));
+    DrawRectangleLinesEx(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), guiAlpha));
+    GuiDrawText(items[itemSelected], GetTextBounds(DEFAULT, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)), guiAlpha));
+
+    if (editMode)
+    {
+        // Draw visible items
+        for (int i = 0; i < itemsCount; i++)
+        {
+            // Update item rectangle y position for next item
+            itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
+
+            if (i == itemSelected)
+            {
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+                GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)), guiAlpha));
+            }
+            else if (i == itemFocused)
+            {
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), guiAlpha));
+                GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)), guiAlpha));
+            }
+            else GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)), guiAlpha));
+        }
+    }
+
+    // TODO: Avoid this function, use icon instead or 'v'
+    DrawTriangle(RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2 },
+                 RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING) + 5, bounds.y + bounds.height/2 - 2 + 5 },
+                 RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING) + 10, bounds.y + bounds.height/2 - 2 },
+                 Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
+
+    //GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
+    //            GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    *active = itemSelected;
+    return pressed;
+}
+
+// Text Box control, updates input text
+// NOTE 1: Requires static variables: framesCounter
+// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
+bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+    static int framesCounter = 0;           // Required for blinking cursor
+
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    Rectangle cursor = {
+        bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text) + 2,
+        bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
+        1,
+        GuiGetStyle(DEFAULT, TEXT_SIZE)*2
+    };
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (editMode)
+        {
+            state = GUI_STATE_PRESSED;
+            framesCounter++;
+
+            int key = GetKeyPressed();
+            int keyCount = strlen(text);
+
+            // Only allow keys in range [32..125]
+            if (keyCount < (textSize - 1))
+            {
+                int maxWidth = (bounds.width - (GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)*2));
+
+                if (GetTextWidth(text) < (maxWidth - GuiGetStyle(DEFAULT, TEXT_SIZE)))
+                {
+                    if (((key >= 32) && (key <= 125)) ||
+                        ((key >= 128) && (key < 255)))
+                    {
+                        text[keyCount] = (char)key;
+                        keyCount++;
+                        text[keyCount] = '\0';
+                    }
+                }
+            }
+
+            // Delete text
+            if (keyCount > 0)
+            {
+                if (IsKeyPressed(KEY_BACKSPACE))
+                {
+                    keyCount--;
+                    text[keyCount] = '\0';
+                    framesCounter = 0;
+                    if (keyCount < 0) keyCount = 0;
+                }
+                else if (IsKeyDown(KEY_BACKSPACE))
+                {
+                    if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
+                    text[keyCount] = '\0';
+                    if (keyCount < 0) keyCount = 0;
+                }
+            }
+
+            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(0))) pressed = true;
+
+            // Check text alignment to position cursor properly
+            int textAlignment = GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT);
+            if (textAlignment == GUI_TEXT_ALIGN_CENTER) cursor.x = bounds.x + GetTextWidth(text)/2 + bounds.width/2 + 1;
+            else if (textAlignment == GUI_TEXT_ALIGN_RIGHT) cursor.x = bounds.x + bounds.width - GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING);
+        }
+        else
+        {
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                state = GUI_STATE_FOCUSED;
+                if (IsMouseButtonPressed(0)) pressed = true;
+            }
+        }
+
+        if (pressed) framesCounter = 0;
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha));
+
+    if (state == GUI_STATE_PRESSED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
+
+        // Draw blinking cursor
+        if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangleRec(cursor, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+    }
+    else if (state == GUI_STATE_DISABLED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
+    }
+
+    GuiDrawText(text, GetTextBounds(TEXTBOX, bounds), GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return pressed;
+}
+
+// Spinner control, returns selected value
+bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
+{
+    GuiControlState state = guiState;
+
+    bool pressed = false;
+    int tempValue = *value;
+
+    Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_PADDING), bounds.y,
+                          bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_PADDING)), bounds.height };
+    Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
+    Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
+
+    Rectangle textBounds = { 0 };
+    if (text != NULL)
+    {
+        textBounds.width = GetTextWidth(text);
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(SPINNER, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+        if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING);
+    }
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check spinner state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+
+    if (!editMode)
+    {
+        if (tempValue < minValue) tempValue = minValue;
+        if (tempValue > maxValue) tempValue = maxValue;
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    // TODO: Set Spinner properties for ValueBox
+    pressed = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode);
+
+    // Draw value selector custom buttons
+    // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
+    int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+    int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH));
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+
+#if defined(RAYGUI_SUPPORT_ICONS)
+    if (GuiButton(leftButtonBound, GuiIconText(RICON_ARROW_LEFT_FILL, NULL))) tempValue--;
+    if (GuiButton(rightButtonBound, GuiIconText(RICON_ARROW_RIGHT_FILL, NULL))) tempValue++;
+#else
+    if (GuiButton(leftButtonBound, "<")) tempValue--;
+    if (GuiButton(rightButtonBound, ">")) tempValue++;
+#endif
+
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+
+    // Draw text label if provided
+    if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    *value = tempValue;
+    return pressed;
+}
+
+// Value Box control, updates input text with numbers
+// NOTE: Requires static variables: framesCounter
+bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
+{
+    #if !defined(VALUEBOX_MAX_CHARS)
+        #define VALUEBOX_MAX_CHARS  32
+    #endif
+
+    static int framesCounter = 0;           // Required for blinking cursor
+
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    char textValue[VALUEBOX_MAX_CHARS + 1] = "\0";
+    sprintf(textValue, "%i", *value);
+
+    Rectangle textBounds = { 0 };
+    if (text != NULL)
+    {
+        textBounds.width = GetTextWidth(text);
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+        if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+    }
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        bool valueHasChanged = false;
+
+        if (editMode)
+        {
+            state = GUI_STATE_PRESSED;
+
+            framesCounter++;
+
+            int keyCount = strlen(textValue);
+
+            // Only allow keys in range [48..57]
+            if (keyCount < VALUEBOX_MAX_CHARS)
+            {
+                int maxWidth = bounds.width;
+                if (GetTextWidth(textValue) < maxWidth)
+                {
+                    int key = GetKeyPressed();
+                    if ((key >= 48) && (key <= 57))
+                    {
+                        textValue[keyCount] = (char)key;
+                        keyCount++;
+                        valueHasChanged = true;
+                    }
+                }
+            }
+
+            // Delete text
+            if (keyCount > 0)
+            {
+                if (IsKeyPressed(KEY_BACKSPACE))
+                {
+                    keyCount--;
+                    textValue[keyCount] = '\0';
+                    framesCounter = 0;
+                    if (keyCount < 0) keyCount = 0;
+                    valueHasChanged = true;
+                }
+                else if (IsKeyDown(KEY_BACKSPACE))
+                {
+                    if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
+                    textValue[keyCount] = '\0';
+                    if (keyCount < 0) keyCount = 0;
+                    valueHasChanged = true;
+                }
+            }
+
+            if (valueHasChanged) *value = TextToInteger(textValue);
+
+            if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(0))) pressed = true;
+        }
+        else
+        {
+            if (*value > maxValue) *value = maxValue;
+            else if (*value < minValue) *value = minValue;
+
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                state = GUI_STATE_FOCUSED;
+                if (IsMouseButtonPressed(0)) pressed = true;
+            }
+        }
+
+        if (pressed) framesCounter = 0;
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha));
+
+    if (state == GUI_STATE_PRESSED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)), guiAlpha));
+
+        // Draw blinking cursor
+        // NOTE: ValueBox internal text is always centered
+        if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangle(bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+    }
+    else if (state == GUI_STATE_DISABLED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)), guiAlpha));
+    }
+
+    GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
+
+    // Draw text label if provided
+    if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return pressed;
+}
+
+// Text Box control with multiple lines
+bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+    static int framesCounter = 0;           // Required for blinking cursor
+
+    GuiControlState state = guiState;
+    bool pressed = false;
+
+    Rectangle textAreaBounds = {
+        bounds.x + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
+        bounds.y + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
+        bounds.width - 2*GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
+        bounds.height - 2*GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)
+    };
+
+    bool textHasChange = false;
+    int currentLine = 0;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (editMode)
+        {
+            state = GUI_STATE_PRESSED;
+            framesCounter++;
+
+            int keyCount = strlen(text);
+            int maxWidth = textAreaBounds.width;
+            int maxHeight = textAreaBounds.height;
+
+            // Only allow keys in range [32..125]
+            if (keyCount < (textSize - 1))
+            {
+                int key = GetKeyPressed();
+
+                if (MeasureTextEx(guiFont, text, GuiGetStyle(DEFAULT, TEXT_SIZE), 1).y < (maxHeight - GuiGetStyle(DEFAULT, TEXT_SIZE)))
+                {
+                    if (IsKeyPressed(KEY_ENTER))
+                    {
+                        text[keyCount] = '\n';
+                        keyCount++;
+                    }
+                    else if (((key >= 32) && (key <= 125)) || ((key >= 128) && (key < 255)))
+                    {
+                        text[keyCount] = (char)key;
+                        keyCount++;
+                        textHasChange = true;
+                    }
+                }
+                else if (GetTextWidth(strrchr(text, '\n')) < (maxWidth - GuiGetStyle(DEFAULT, TEXT_SIZE)))
+                {
+                    if (((key >= 32) && (key <= 125)) || ((key >= 128) && (key < 255)))
+                    {
+                        text[keyCount] = (char)key;
+                        keyCount++;
+                        textHasChange = true;
+                    }
+                }
+            }
+
+            // Delete text
+            if (keyCount > 0)
+            {
+                if (IsKeyPressed(KEY_BACKSPACE))
+                {
+                    keyCount--;
+                    text[keyCount] = '\0';
+                    framesCounter = 0;
+                    if (keyCount < 0) keyCount = 0;
+                    textHasChange = true;
+                }
+                else if (IsKeyDown(KEY_BACKSPACE))
+                {
+                    if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
+                    text[keyCount] = '\0';
+
+                    if (keyCount < 0) keyCount = 0;
+                    textHasChange = true;
+                }
+            }
+
+            // Introduce automatic new line if necessary
+            if (textHasChange)
+            {
+                textHasChange = false;
+
+                char *lastLine = strrchr(text, '\n');
+                int maxWidth = (bounds.width - (GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)*2));
+
+                if (lastLine != NULL)
+                {
+                    if (GetTextWidth(lastLine) > maxWidth)
+                    {
+                        int firstIndex = lastLine - text;
+
+                        char *lastSpace = strrchr(lastLine, 32);
+
+                        if (lastSpace != NULL)
+                        {
+                            int secondIndex = lastSpace - lastLine;
+                            text[firstIndex + secondIndex] = '\n';
+                        }
+                        else
+                        {
+                            int len = (lastLine != NULL)? strlen(lastLine) : 0;
+                            char lastChar = lastLine[len - 1];
+                            lastLine[len - 1] = '\n';
+                            lastLine[len] = lastChar;
+                            lastLine[len + 1] = '\0';
+                            keyCount++;
+                        }
+                    }
+                }
+                else
+                {
+                    if (GetTextWidth(text) > maxWidth)
+                    {
+                        char *lastSpace = strrchr(text, 32);
+
+                        if (lastSpace != NULL)
+                        {
+                            int index = lastSpace - text;
+                            text[index] = '\n';
+                        }
+                        else
+                        {
+                            int len = (lastLine != NULL)? strlen(lastLine) : 0;
+                            char lastChar = lastLine[len - 1];
+                            lastLine[len - 1] = '\n';
+                            lastLine[len] = lastChar;
+                            lastLine[len + 1] = '\0';
+                            keyCount++;
+                        }
+                    }
+                }
+            }
+
+            // Counting how many new lines
+            for (int i = 0; i < keyCount; i++)
+            {
+                if (text[i] == '\n') currentLine++;
+            }
+
+            // Exit edit mode
+            if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(0)) pressed = true;
+        }
+        else
+        {
+            if (CheckCollisionPointRec(mousePoint, bounds))
+            {
+                state = GUI_STATE_FOCUSED;
+                if (IsMouseButtonPressed(0)) pressed = true;
+            }
+        }
+
+        if (pressed) framesCounter = 0;     // Reset blinking cursor
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha));
+
+    if (state == GUI_STATE_PRESSED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
+
+        // Draw blinking cursor
+        if (editMode && ((framesCounter/20)%2 == 0))
+        {
+            char *line = NULL;
+            if (currentLine > 0) line = strrchr(text, '\n');
+            else line = text;
+
+            Rectangle cursor = {
+                bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING) + GetTextWidth(line),
+                bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)/2 + ((GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING))*currentLine),
+                1, GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)
+            };
+
+            DrawRectangleRec(cursor, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+        }
+    }
+    else if (state == GUI_STATE_DISABLED)
+    {
+        DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
+    }
+
+    DrawTextRec(guiFont, text, textAreaBounds, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING), true, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return pressed;
+}
+
+// Slider control with pro parameters
+// NOTE: Other GuiSlider*() controls use this one
+float GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue, int sliderWidth)
+{
+    GuiControlState state = guiState;
+
+    int sliderValue = (int)(((value - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
+
+    Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+                         0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
+
+    if (sliderWidth > 0)        // Slider
+    {
+        slider.x += (sliderValue - sliderWidth/2);
+        slider.width = sliderWidth;
+    }
+    else if (sliderWidth == 0)  // SliderBar
+    {
+        slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
+        slider.width = sliderValue;
+    }
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+            {
+                state = GUI_STATE_PRESSED;
+
+                // Get equivalent value and slider position from mousePoint.x
+                value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
+
+                if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2;  // Slider
+                else if (sliderWidth == 0) slider.width = sliderValue;          // SliderBar
+            }
+            else state = GUI_STATE_FOCUSED;
+        }
+
+        if (value > maxValue) value = maxValue;
+        else if (value < minValue) value = minValue;
+    }
+
+    // Bar limits check
+    if (sliderWidth > 0)        // Slider
+    {
+        if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
+        else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
+    }
+    else if (sliderWidth == 0)  // SliderBar
+    {
+        if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha));
+    DrawRectangle(bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, (state != GUI_STATE_DISABLED)?  BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+    // Draw slider internal bar (depends on state)
+    if ((state == GUI_STATE_NORMAL) || (state == GUI_STATE_PRESSED)) DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
+    else if (state == GUI_STATE_FOCUSED) DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
+
+    // Draw left/right text if provided
+    if (textLeft != NULL)
+    {
+        Rectangle textBounds = { 0 };
+        textBounds.width = GetTextWidth(textLeft);  // TODO: Consider text icon
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+        GuiDrawText(textLeft, textBounds, GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+    }
+
+    if (textRight != NULL)
+    {
+        Rectangle textBounds = { 0 };
+        textBounds.width = GetTextWidth(textRight);  // TODO: Consider text icon
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+        GuiDrawText(textRight, textBounds, GUI_TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+    }
+    //--------------------------------------------------------------------
+
+    return value;
+}
+
+// Slider control extended, returns selected value and has text
+float GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
+{
+    return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH));
+}
+
+// Slider Bar control extended, returns selected value
+float GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
+{
+    return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0);
+}
+
+// Progress Bar control extended, shows current progress value
+float GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
+{
+    GuiControlState state = guiState;
+
+    Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
+                           bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
+                           bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) };
+
+    // Update control
+    //--------------------------------------------------------------------
+    if (state != GUI_STATE_DISABLED) progress.width = (int)(value/(maxValue - minValue)*(float)(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)));
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), guiAlpha));
+
+    // Draw slider internal progress bar (depends on state)
+    if ((state == GUI_STATE_NORMAL) || (state == GUI_STATE_PRESSED)) DrawRectangleRec(progress, Fade(GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)), guiAlpha));
+    else if (state == GUI_STATE_FOCUSED) DrawRectangleRec(progress, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT_COLOR_FOCUSED)), guiAlpha));
+
+    // Draw left/right text if provided
+    if (textLeft != NULL)
+    {
+        Rectangle textBounds = { 0 };
+        textBounds.width = GetTextWidth(textLeft);  // TODO: Consider text icon
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+        GuiDrawText(textLeft, textBounds, GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
+    }
+
+    if (textRight != NULL)
+    {
+        Rectangle textBounds = { 0 };
+        textBounds.width = GetTextWidth(textRight);  // TODO: Consider text icon
+        textBounds.height = GuiGetStyle(DEFAULT, TEXT_SIZE);
+        textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
+        textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+        GuiDrawText(textRight, textBounds, GUI_TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
+    }
+    //--------------------------------------------------------------------
+
+    return value;
+}
+
+// Status Bar control
+void GuiStatusBar(Rectangle bounds, const char *text)
+{
+    GuiControlState state = guiState;
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleLinesEx(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != GUI_STATE_DISABLED)? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED)), guiAlpha));
+    DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(STATUSBAR, BORDER_WIDTH), bounds.y + GuiGetStyle(STATUSBAR, BORDER_WIDTH), bounds.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH)*2, bounds.height - GuiGetStyle(STATUSBAR, BORDER_WIDTH)*2 }, Fade(GetColor(GuiGetStyle(STATUSBAR, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+    GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != GUI_STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
+    //--------------------------------------------------------------------
+}
+
+// Dummy rectangle control, intended for placeholding
+void GuiDummyRec(Rectangle bounds, const char *text)
+{
+    GuiControlState state = guiState;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check button state
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+    GuiDrawText(text, GetTextBounds(DEFAULT, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(BUTTON, (state != GUI_STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
+    //------------------------------------------------------------------
+}
+
+// Scroll Bar control
+// TODO: I feel GuiScrollBar could be simplified...
+int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
+{
+    GuiControlState state = guiState;
+
+    // Is the scrollbar horizontal or vertical?
+    bool isVertical = (bounds.width > bounds.height)? false : true;
+
+    // The size (width or height depending on scrollbar type) of the spinner buttons
+    const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? (isVertical? bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0;
+
+    // Arrow buttons [<] [>] [∧] [∨]
+    Rectangle arrowUpLeft = { 0 };
+    Rectangle arrowDownRight = { 0 };
+
+    // Actual area of the scrollbar excluding the arrow buttons
+    Rectangle scrollbar = { 0 };
+
+    // Slider bar that moves     --[///]-----
+    Rectangle slider = { 0 };
+
+    // Normalize value
+    if (value > maxValue) value = maxValue;
+    if (value < minValue) value = minValue;
+
+    const int range = maxValue - minValue;
+    int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+
+    // Calculate rectangles for all of the components
+    arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize };
+
+    if (isVertical)
+    {
+        arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize};
+        scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) };
+        sliderSize = (sliderSize >= scrollbar.height)? (scrollbar.height - 2) : sliderSize;     // Make sure the slider won't get outside of the scrollbar
+        slider = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), (float)scrollbar.y + (int)(((float)(value - minValue)/range)*(scrollbar.height - sliderSize)), (float)bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), (float)sliderSize };
+    }
+    else
+    {
+        arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize};
+        scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING))};
+        sliderSize = (sliderSize >= scrollbar.width)? (scrollbar.width - 2) : sliderSize;       // Make sure the slider won't get outside of the scrollbar
+        slider = RAYGUI_CLITERAL(Rectangle){ (float)scrollbar.x + (int)(((float)(value - minValue)/range)*(scrollbar.width - sliderSize)), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), (float)sliderSize, (float)bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) };
+    }
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            state = GUI_STATE_FOCUSED;
+
+            // Handle mouse wheel
+            int wheel = GetMouseWheelMove();
+            if (wheel != 0) value += wheel;
+
+            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+            {
+                if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+                else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+
+                state = GUI_STATE_PRESSED;
+            }
+            else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+            {
+                if (!isVertical)
+                {
+                    Rectangle scrollArea = { arrowUpLeft.x + arrowUpLeft.width, arrowUpLeft.y, scrollbar.width, bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)};
+                    if (CheckCollisionPointRec(mousePoint, scrollArea)) value = ((float)(mousePoint.x - scrollArea.x - slider.width/2)*range)/(scrollArea.width - slider.width) + minValue;
+                }
+                else
+                {
+                    Rectangle scrollArea = { arrowUpLeft.x, arrowUpLeft.y+arrowUpLeft.height, bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH),  scrollbar.height};
+                    if (CheckCollisionPointRec(mousePoint, scrollArea)) value = ((float)(mousePoint.y - scrollArea.y - slider.height/2)*range)/(scrollArea.height - slider.height) + minValue;
+                }
+            }
+        }
+
+        // Normalize value
+        if (value > maxValue) value = maxValue;
+        if (value < minValue) value = minValue;
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED)), guiAlpha));   // Draw the background
+    DrawRectangleRec(scrollbar, Fade(GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)), guiAlpha));     // Draw the scrollbar active area background
+
+    DrawRectangleLinesEx(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
+
+    DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, BORDER + state*3)), guiAlpha));         // Draw the slider bar
+
+    // Draw arrows
+    const int padding = (spinnerSize - GuiGetStyle(SCROLLBAR, ARROWS_SIZE))/2;
+    const Vector2 lineCoords[] =
+    {
+        // Coordinates for <     0,1,2
+        { arrowUpLeft.x + padding, arrowUpLeft.y + spinnerSize/2 },
+        { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + padding },
+        { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + spinnerSize - padding },
+
+        // Coordinates for >     3,4,5
+        { arrowDownRight.x + padding, arrowDownRight.y + padding },
+        { arrowDownRight.x + spinnerSize - padding, arrowDownRight.y + spinnerSize/2 },
+        { arrowDownRight.x + padding, arrowDownRight.y + spinnerSize - padding },
+
+        // Coordinates for ∧     6,7,8
+        { arrowUpLeft.x + spinnerSize/2, arrowUpLeft.y + padding },
+        { arrowUpLeft.x + padding, arrowUpLeft.y + spinnerSize - padding },
+        { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + spinnerSize - padding },
+
+        // Coordinates for ∨     9,10,11
+        { arrowDownRight.x + padding, arrowDownRight.y + padding },
+        { arrowDownRight.x + spinnerSize/2, arrowDownRight.y + spinnerSize - padding },
+        { arrowDownRight.x + spinnerSize - padding, arrowDownRight.y + padding }
+    };
+
+    Color lineColor = Fade(GetColor(GuiGetStyle(BUTTON, TEXT + state*3)), guiAlpha);
+
+    if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE))
+    {
+        if (isVertical)
+        {
+            DrawTriangle(lineCoords[6], lineCoords[7], lineCoords[8], lineColor);
+            DrawTriangle(lineCoords[9], lineCoords[10], lineCoords[11], lineColor);
+        }
+        else
+        {
+            DrawTriangle(lineCoords[2], lineCoords[1], lineCoords[0], lineColor);
+            DrawTriangle(lineCoords[5], lineCoords[4], lineCoords[3], lineColor);
+        }
+    }
+    //--------------------------------------------------------------------
+
+    return value;
+}
+
+// List View control
+int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active)
+{
+    int itemsCount = 0;
+    const char **items = NULL;
+
+    if (text != NULL) items = GuiTextSplit(text, &itemsCount, NULL);
+
+    return GuiListViewEx(bounds, items, itemsCount, NULL, scrollIndex, active);
+}
+
+// List View control with extended parameters
+int GuiListViewEx(Rectangle bounds, const char **text, int count, int *focus, int *scrollIndex, int active)
+{
+    GuiControlState state = guiState;
+    int itemFocused = (focus == NULL)? -1 : *focus;
+    int itemSelected = active;
+
+    // Check if we need a scroll bar
+    bool useScrollBar = false;
+    if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING))*count > bounds.height) useScrollBar = true;
+
+    // Define base item rectangle [0]
+    Rectangle itemBounds = { 0 };
+    itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING);
+    itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+    if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+
+    // Get items on the list
+    int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+    if (visibleItems > count) visibleItems = count;
+
+    int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
+    if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
+    int endIndex = startIndex + visibleItems;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        // Check mouse inside list view
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            state = GUI_STATE_FOCUSED;
+
+            // Check focused and selected item
+            for (int i = 0; i < visibleItems; i++)
+            {
+                if (CheckCollisionPointRec(mousePoint, itemBounds))
+                {
+                    itemFocused = startIndex + i;
+                    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+                    {
+                        if (itemSelected == (startIndex + i)) itemSelected = -1;
+                        else itemSelected = startIndex + i;
+                    }
+                    break;
+                }
+
+                // Update item rectangle y position for next item
+                itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+            }
+
+            if (useScrollBar)
+            {
+                int wheelMove = GetMouseWheelMove();
+                startIndex -= wheelMove;
+
+                if (startIndex < 0) startIndex = 0;
+                else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
+
+                endIndex = startIndex + visibleItems;
+                if (endIndex > count) endIndex = count;
+            }
+        }
+        else itemFocused = -1;
+
+        // Reset item rectangle y to [0]
+        itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));     // Draw background
+    DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
+
+    // Draw visible items
+    for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
+    {
+        if (state == GUI_STATE_DISABLED)
+        {
+            if ((startIndex + i) == itemSelected)
+            {
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha));
+            }
+
+            GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
+        }
+        else
+        {
+            if ((startIndex + i) == itemSelected)
+            {
+                // Draw item selected
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha));
+                GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
+            }
+            else if ((startIndex + i) == itemFocused)
+            {
+                // Draw item focused
+                DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
+                DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha));
+                GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
+            }
+            else
+            {
+                // Draw item normal
+                GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
+            }
+        }
+
+        // Update item rectangle y position for next item
+        itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+    }
+
+    if (useScrollBar)
+    {
+        Rectangle scrollBarBounds = {
+            bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+            bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+            bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
+        };
+
+        // Calculate percentage of visible items and apply same percentage to scrollbar
+        float percentVisible = (float)(endIndex - startIndex)/count;
+        float sliderSize = bounds.height*percentVisible;
+
+        int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);   // Save default slider size
+        int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
+        GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, sliderSize);            // Change slider size
+        GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
+
+        startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
+
+        GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
+        GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default
+    }
+    //--------------------------------------------------------------------
+
+    if (focus != NULL) *focus = itemFocused;
+    if (scrollIndex != NULL) *scrollIndex = startIndex;
+
+    return itemSelected;
+}
+
+// Color Panel control
+Color GuiColorPanelEx(Rectangle bounds, Color color, float hue)
+{
+    GuiControlState state = guiState;
+    Vector2 pickerSelector = { 0 };
+
+    Vector3 vcolor = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
+    Vector3 hsv = ConvertRGBtoHSV(vcolor);
+
+    pickerSelector.x = bounds.x + (float)hsv.y*bounds.width;            // HSV: Saturation
+    pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height;  // HSV: Value
+
+    Vector3 maxHue = { hue >= 0.0f ? hue : hsv.x, 1.0f, 1.0f };
+    Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
+    Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
+                      (unsigned char)(255.0f*rgbHue.y),
+                      (unsigned char)(255.0f*rgbHue.z), 255 };
+
+    const Color colWhite = { 255, 255, 255, 255 };
+    const Color colBlack = { 0, 0, 0, 255 };
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+            {
+                state = GUI_STATE_PRESSED;
+                pickerSelector = mousePoint;
+
+                // Calculate color from picker
+                Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
+
+                colorPick.x /= (float)bounds.width;     // Get normalized value on x
+                colorPick.y /= (float)bounds.height;    // Get normalized value on y
+
+                hsv.y = colorPick.x;
+                hsv.z = 1.0f - colorPick.y;
+
+                Vector3 rgb = ConvertHSVtoRGB(hsv);
+
+                // NOTE: Vector3ToColor() only available on raylib 1.8.1
+                color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
+                                 (unsigned char)(255.0f*rgb.y),
+                                 (unsigned char)(255.0f*rgb.z),
+                                 (unsigned char)(255.0f*(float)color.a/255.0f) };
+
+            }
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (state != GUI_STATE_DISABLED)
+    {
+        DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
+        DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
+
+        // Draw color picker: selector
+        DrawRectangle(pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), Fade(colWhite, guiAlpha));
+    }
+    else
+    {
+        DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
+    }
+
+    DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return color;
+}
+
+Color GuiColorPanel(Rectangle bounds, Color color)
+{
+    return GuiColorPanelEx(bounds, color, -1.0f);
+}
+
+// Color Bar Alpha control
+// NOTE: Returns alpha value normalized [0..1]
+float GuiColorBarAlpha(Rectangle bounds, float alpha)
+{
+    #define COLORBARALPHA_CHECKED_SIZE   10
+
+    GuiControlState state = guiState;
+    Rectangle selector = { (float)bounds.x + alpha*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 };
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds) ||
+            CheckCollisionPointRec(mousePoint, selector))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+            {
+                state = GUI_STATE_PRESSED;
+                selector.x = mousePoint.x - selector.width/2;
+
+                alpha = (mousePoint.x - bounds.x)/bounds.width;
+                if (alpha <= 0.0f) alpha = 0.0f;
+                if (alpha >= 1.0f) alpha = 1.0f;
+                //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2;
+            }
+            else state = GUI_STATE_FOCUSED;
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+
+    // Draw alpha bar: checked background
+    if (state != GUI_STATE_DISABLED)
+    {
+        int checksX = bounds.width/COLORBARALPHA_CHECKED_SIZE;
+        int checksY = bounds.height/COLORBARALPHA_CHECKED_SIZE;
+
+        for (int x = 0; x < checksX; x++)
+        {
+            for (int y = 0; y < checksY; y++)
+            {
+                DrawRectangle(bounds.x + x*COLORBARALPHA_CHECKED_SIZE,
+                              bounds.y + y*COLORBARALPHA_CHECKED_SIZE,
+                              COLORBARALPHA_CHECKED_SIZE, COLORBARALPHA_CHECKED_SIZE,
+                              ((x + y)%2)? Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f), guiAlpha) :
+                                     Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f), guiAlpha));
+            }
+        }
+
+        DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha));
+    }
+    else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
+
+    DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+
+    // Draw alpha bar: selector
+    DrawRectangleRec(selector, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return alpha;
+}
+
+// Color Bar Hue control
+// NOTE: Returns hue value normalized [0..1]
+float GuiColorBarHue(Rectangle bounds, float hue)
+{
+    GuiControlState state = guiState;
+    Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + hue/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) };
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        Vector2 mousePoint = GetMousePosition();
+
+        if (CheckCollisionPointRec(mousePoint, bounds) ||
+            CheckCollisionPointRec(mousePoint, selector))
+        {
+            if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+            {
+                state = GUI_STATE_PRESSED;
+                selector.y = mousePoint.y - selector.height/2;
+
+                hue = (mousePoint.y - bounds.y)*360/bounds.height;
+                if (hue <= 0.0f) hue = 0.0f;
+                if (hue >= 359.0f) hue = 359.0f;
+
+            }
+            else state = GUI_STATE_FOCUSED;
+
+            /*if (IsKeyDown(KEY_UP))
+            {
+                hue -= 2.0f;
+                if (hue <= 0.0f) hue = 0.0f;
+            }
+            else if (IsKeyDown(KEY_DOWN))
+            {
+                hue += 2.0f;
+                if (hue >= 360.0f) hue = 360.0f;
+            }*/
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (state != GUI_STATE_DISABLED)
+    {
+        // Draw hue bar:color bars
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 255,0,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,255,0,255 }, guiAlpha));
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + (int)bounds.height/6 + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 255,255,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,255,0,255 }, guiAlpha));
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + 2*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,255,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,255,255,255 }, guiAlpha));
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + 3*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,255,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,0,255,255 }, guiAlpha));
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + 4*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,0,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,0,255,255 }, guiAlpha));
+        DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.y + 5*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)/2, bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (int)bounds.height/6 - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), Fade(RAYGUI_CLITERAL(Color){ 255,0,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,0,0,255 }, guiAlpha));
+    }
+    else DrawRectangleGradientV(bounds.x, bounds.y, bounds.width, bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
+
+    DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+
+    // Draw hue bar: selector
+    DrawRectangleRec(selector, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+    //--------------------------------------------------------------------
+
+    return hue;
+}
+
+// TODO: Color GuiColorBarSat() [WHITE->color]
+// TODO: Color GuiColorBarValue() [BLACK->color], HSV / HSL
+// TODO: float GuiColorBarLuminance() [BLACK->WHITE]
+
+// Color Picker control
+// NOTE: It's divided in multiple controls:
+//      Color GuiColorPanel() - Color select panel
+//      float GuiColorBarAlpha(Rectangle bounds, float alpha)
+//      float GuiColorBarHue(Rectangle bounds, float value)
+// NOTE: bounds define GuiColorPanel() size
+Color GuiColorPicker(Rectangle bounds, Color color)
+{
+    color = GuiColorPanel(bounds, color);
+
+    Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
+    //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
+
+    Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ color.r/255.0f, color.g/255.0f, color.b/255.0f });
+    hsv.x = GuiColorBarHue(boundsHue, hsv.x);
+    //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
+    Vector3 rgb = ConvertHSVtoRGB(hsv);
+    color = RAYGUI_CLITERAL(Color){ (unsigned char)(rgb.x*255.0f), (unsigned char)(rgb.y*255.0f), (unsigned char)(rgb.z*255.0f), color.a };
+
+    return color;
+}
+
+// Message Box control
+int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons)
+{
+    #define MESSAGEBOX_BUTTON_HEIGHT    24
+    #define MESSAGEBOX_BUTTON_PADDING   10
+
+    int clicked = -1;    // Returns clicked button from buttons list, 0 refers to closed window button
+
+    int buttonsCount = 0;
+    const char **buttonsText = GuiTextSplit(buttons, &buttonsCount, NULL);
+    Rectangle buttonBounds = { 0 };
+    buttonBounds.x = bounds.x + MESSAGEBOX_BUTTON_PADDING;
+    buttonBounds.y = bounds.y + bounds.height - MESSAGEBOX_BUTTON_HEIGHT - MESSAGEBOX_BUTTON_PADDING;
+    buttonBounds.width = (bounds.width - MESSAGEBOX_BUTTON_PADDING*(buttonsCount + 1))/buttonsCount;
+    buttonBounds.height = MESSAGEBOX_BUTTON_HEIGHT;
+
+    Vector2 textSize = MeasureTextEx(guiFont, message, GuiGetStyle(DEFAULT, TEXT_SIZE), 1);
+
+    Rectangle textBounds = { 0 };
+    textBounds.x = bounds.x + bounds.width/2 - textSize.x/2;
+    textBounds.y = bounds.y + WINDOW_STATUSBAR_HEIGHT + (bounds.height - WINDOW_STATUSBAR_HEIGHT - MESSAGEBOX_BUTTON_HEIGHT - MESSAGEBOX_BUTTON_PADDING)/2 - textSize.y/2;
+    textBounds.width = textSize.x;
+    textBounds.height = textSize.y;
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (GuiWindowBox(bounds, title)) clicked = 0;
+
+    int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
+    GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+    GuiLabel(textBounds, message);
+    GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
+
+    prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+
+    for (int i = 0; i < buttonsCount; i++)
+    {
+        if (GuiButton(buttonBounds, buttonsText[i])) clicked = i + 1;
+        buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
+    }
+
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment);
+    //--------------------------------------------------------------------
+
+    return clicked;
+}
+
+// Text Input Box control, ask for text
+int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text)
+{
+    #define TEXTINPUTBOX_BUTTON_HEIGHT      24
+    #define TEXTINPUTBOX_BUTTON_PADDING     10
+    #define TEXTINPUTBOX_HEIGHT             30
+
+    #define TEXTINPUTBOX_MAX_TEXT_LENGTH   256
+
+    // Used to enable text edit mode
+    // WARNING: No more than one GuiTextInputBox() should be open at the same time
+    static bool textEditMode = false;
+
+    int btnIndex = -1;
+
+    int buttonsCount = 0;
+    const char **buttonsText = GuiTextSplit(buttons, &buttonsCount, NULL);
+    Rectangle buttonBounds = { 0 };
+    buttonBounds.x = bounds.x + TEXTINPUTBOX_BUTTON_PADDING;
+    buttonBounds.y = bounds.y + bounds.height - TEXTINPUTBOX_BUTTON_HEIGHT - TEXTINPUTBOX_BUTTON_PADDING;
+    buttonBounds.width = (bounds.width - TEXTINPUTBOX_BUTTON_PADDING*(buttonsCount + 1))/buttonsCount;
+    buttonBounds.height = TEXTINPUTBOX_BUTTON_HEIGHT;
+
+    int messageInputHeight = bounds.height - WINDOW_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - TEXTINPUTBOX_BUTTON_HEIGHT - 2*TEXTINPUTBOX_BUTTON_PADDING;
+
+    Rectangle textBounds = { 0 };
+    if (message != NULL)
+    {
+        Vector2 textSize = MeasureTextEx(guiFont, message, GuiGetStyle(DEFAULT, TEXT_SIZE), 1);
+
+        textBounds.x = bounds.x + bounds.width/2 - textSize.x/2;
+        textBounds.y = bounds.y + WINDOW_STATUSBAR_HEIGHT + messageInputHeight/4 - textSize.y/2;
+        textBounds.width = textSize.x;
+        textBounds.height = textSize.y;
+    }
+
+    Rectangle textBoxBounds = { 0 };
+    textBoxBounds.x = bounds.x + TEXTINPUTBOX_BUTTON_PADDING;
+    textBoxBounds.y = bounds.y + WINDOW_STATUSBAR_HEIGHT - TEXTINPUTBOX_HEIGHT/2;
+    if (message == NULL) textBoxBounds.y += messageInputHeight/2;
+    else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4);
+    textBoxBounds.width = bounds.width - TEXTINPUTBOX_BUTTON_PADDING*2;
+    textBoxBounds.height = TEXTINPUTBOX_HEIGHT;
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (GuiWindowBox(bounds, title)) btnIndex = 0;
+
+    // Draw message if available
+    if (message != NULL)
+    {
+        int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
+        GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+        GuiLabel(textBounds, message);
+        GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
+    }
+
+    if (GuiTextBox(textBoxBounds, text, TEXTINPUTBOX_MAX_TEXT_LENGTH, textEditMode)) textEditMode = !textEditMode;
+
+    int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
+
+    for (int i = 0; i < buttonsCount; i++)
+    {
+        if (GuiButton(buttonBounds, buttonsText[i])) btnIndex = i + 1;
+        buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
+    }
+
+    GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment);
+    //--------------------------------------------------------------------
+
+    return btnIndex;
+}
+
+// Grid control
+// NOTE: Returns grid mouse-hover selected cell
+// About drawing lines at subpixel spacing, simple put, not easy solution:
+// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster
+Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs)
+{
+    #if !defined(GRID_COLOR_ALPHA)
+        #define GRID_COLOR_ALPHA    0.15f           // Grid lines alpha amount
+    #endif
+
+    GuiControlState state = guiState;
+    Vector2 mousePoint = GetMousePosition();
+    Vector2 currentCell = { -1, -1 };
+
+    int linesV = ((int)(bounds.width/spacing))*subdivs + 1;
+    int linesH = ((int)(bounds.height/spacing))*subdivs + 1;
+
+    // Update control
+    //--------------------------------------------------------------------
+    if ((state != GUI_STATE_DISABLED) && !guiLocked)
+    {
+        if (CheckCollisionPointRec(mousePoint, bounds))
+        {
+            currentCell.x = (int)((mousePoint.x - bounds.x)/spacing);
+            currentCell.y = (int)((mousePoint.y - bounds.y)/spacing);
+        }
+    }
+    //--------------------------------------------------------------------
+
+    // Draw control
+    //--------------------------------------------------------------------
+    switch (state)
+    {
+        case GUI_STATE_NORMAL:
+        {
+            // Draw vertical grid lines
+            for (int i = 0; i < linesV; i++)
+            {
+                DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA));
+            }
+
+            // Draw horizontal grid lines
+            for (int i = 0; i < linesH; i++)
+            {
+                DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA));
+            }
+
+        } break;
+        default: break;
+    }
+
+    return currentCell;
+}
+
+//----------------------------------------------------------------------------------
+// Styles loading functions
+//----------------------------------------------------------------------------------
+
+// Load raygui style file (.rgs)
+void GuiLoadStyle(const char *fileName)
+{
+    bool tryBinary = false;
+
+    // Try reading the files as text file first
+    FILE *rgsFile = fopen(fileName, "rt");
+
+    if (rgsFile != NULL)
+    {
+        char buffer[256] = { 0 };
+        fgets(buffer, 256, rgsFile);
+
+        if (buffer[0] == '#')
+        {
+            int controlId = 0;
+            int propertyId = 0;
+            int propertyValue = 0;
+
+            while (!feof(rgsFile))
+            {
+                switch (buffer[0])
+                {
+                    case 'p':
+                    {
+                        // Style property: p <control_id> <property_id> <property_value> <property_name>
+
+                        sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue);
+
+                        GuiSetStyle(controlId, propertyId, propertyValue);
+
+                    } break;
+                    case 'f':
+                    {
+                        // Style font: f <gen_font_size> <charmap_file> <font_file>
+
+                        int fontSize = 0;
+                        char charmapFileName[256] = { 0 };
+                        char fontFileName[256] = { 0 };
+                        sscanf(buffer, "f %d %s %[^\n]s", &fontSize, charmapFileName, fontFileName);
+
+                        Font font = { 0 };
+
+                        if (charmapFileName[0] != '0')
+                        {
+                            // Load characters from charmap file,
+                            // expected '\n' separated list of integer values
+                            char *charValues = LoadText(charmapFileName);
+                            if (charValues != NULL)
+                            {
+                                int charsCount = 0;
+                                const char **chars = TextSplit(charValues, '\n', &charsCount);
+
+                                int *values = (int *)RAYGUI_MALLOC(charsCount*sizeof(int));
+                                for (int i = 0; i < charsCount; i++) values[i] = TextToInteger(chars[i]);
+
+                                font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, values, charsCount);
+
+                                RAYGUI_FREE(values);
+                            }
+                        }
+                        else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0);
+
+                        if ((font.texture.id > 0) && (font.charsCount > 0)) GuiSetFont(font);
+
+                    } break;
+                    default: break;
+                }
+
+                fgets(buffer, 256, rgsFile);
+            }
+        }
+        else tryBinary = true;
+
+        fclose(rgsFile);
+    }
+
+    if (tryBinary)
+    {
+        rgsFile = fopen(fileName, "rb");
+
+        if (rgsFile == NULL) return;
+
+        char signature[5] = "";
+        short version = 0;
+        short reserved = 0;
+        int propertiesCount = 0;
+
+        fread(signature, 1, 4, rgsFile);
+        fread(&version, 1, sizeof(short), rgsFile);
+        fread(&reserved, 1, sizeof(short), rgsFile);
+        fread(&propertiesCount, 1, sizeof(int), rgsFile);
+
+        if ((signature[0] == 'r') &&
+            (signature[1] == 'G') &&
+            (signature[2] == 'S') &&
+            (signature[3] == ' '))
+        {
+            short controlId = 0;
+            short propertyId = 0;
+            int propertyValue = 0;
+
+            for (int i = 0; i < propertiesCount; i++)
+            {
+                fread(&controlId, 1, sizeof(short), rgsFile);
+                fread(&propertyId, 1, sizeof(short), rgsFile);
+                fread(&propertyValue, 1, sizeof(int), rgsFile);
+
+                if (controlId == 0) // DEFAULT control
+                {
+                    // If a DEFAULT property is loaded, it is propagated to all controls
+                    // NOTE: All DEFAULT properties should be defined first in the file
+                    GuiSetStyle(0, (int)propertyId, propertyValue);
+
+                    if (propertyId < NUM_PROPS_DEFAULT) for (int i = 1; i < NUM_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue);
+                }
+                else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);
+            }
+
+            // Font loading is highly dependant on raylib API to load font data and image
+            // TODO: Find some mechanism to support it in standalone mode
+#if !defined(RAYGUI_STANDALONE)
+            // Load custom font if available
+            int fontDataSize = 0;
+            fread(&fontDataSize, 1, sizeof(int), rgsFile);
+
+            if (fontDataSize > 0)
+            {
+                Font font = { 0 };
+                int fontType = 0;   // 0-Normal, 1-SDF
+                Rectangle whiteRec = { 0 };
+
+                fread(&font.baseSize, 1, sizeof(int), rgsFile);
+                fread(&font.charsCount, 1, sizeof(int), rgsFile);
+                fread(&fontType, 1, sizeof(int), rgsFile);
+
+                // Load font white rectangle
+                fread(&whiteRec, 1, sizeof(Rectangle), rgsFile);
+
+                // Load font image parameters
+                int fontImageSize = 0;
+                fread(&fontImageSize, 1, sizeof(int), rgsFile);
+
+                if (fontImageSize > 0)
+                {
+                    Image imFont = { 0 };
+                    imFont.mipmaps = 1;
+                    fread(&imFont.width, 1, sizeof(int), rgsFile);
+                    fread(&imFont.height, 1, sizeof(int), rgsFile);
+                    fread(&imFont.format, 1, sizeof(int), rgsFile);
+
+                    imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageSize);
+                    fread(imFont.data, 1, fontImageSize, rgsFile);
+
+                    font.texture = LoadTextureFromImage(imFont);
+
+                    UnloadImage(imFont);
+                }
+
+                // Load font recs data
+                font.recs = (Rectangle *)RAYGUI_CALLOC(font.charsCount, sizeof(Rectangle));
+                for (int i = 0; i < font.charsCount; i++) fread(&font.recs[i], 1, sizeof(Rectangle), rgsFile);
+
+                // Load font chars info data
+                font.chars = (CharInfo *)RAYGUI_CALLOC(font.charsCount, sizeof(CharInfo));
+                for (int i = 0; i < font.charsCount; i++)
+                {
+                    fread(&font.chars[i].value, 1, sizeof(int), rgsFile);
+                    fread(&font.chars[i].offsetX, 1, sizeof(int), rgsFile);
+                    fread(&font.chars[i].offsetY, 1, sizeof(int), rgsFile);
+                    fread(&font.chars[i].advanceX, 1, sizeof(int), rgsFile);
+                }
+
+                GuiSetFont(font);
+
+                // Set font texture source rectangle to be used as white texture to draw shapes
+                // NOTE: This way, all gui can be draw using a single draw call
+                if ((whiteRec.width != 0) && (whiteRec.height != 0)) SetShapesTexture(font.texture, whiteRec);
+            }
+#endif
+        }
+
+        fclose(rgsFile);
+    }
+}
+
+// Load style default over global style
+void GuiLoadStyleDefault(void)
+{
+    // We set this variable first to avoid cyclic function calls
+    // when calling GuiSetStyle() and GuiGetStyle()
+    guiStyleLoaded = true;
+
+    // Initialize default LIGHT style property values
+    GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff);
+    GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff);
+    GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff);
+    GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff);
+    GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff);
+    GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff);
+    GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff);
+    GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff);
+    GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff);
+    GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff);
+    GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff);
+    GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff);
+    GuiSetStyle(DEFAULT, BORDER_WIDTH, 1);                       // WARNING: Some controls use other values
+    GuiSetStyle(DEFAULT, TEXT_PADDING, 0);                       // WARNING: Some controls use other values
+    GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); // WARNING: Some controls use other values
+
+    // Initialize control-specific property values
+    // NOTE: Those properties are in default list but require specific values by control type
+    GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+    GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
+    GuiSetStyle(SLIDER, TEXT_PADDING, 5);
+    GuiSetStyle(CHECKBOX, TEXT_PADDING, 5);
+    GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_RIGHT);
+    GuiSetStyle(TEXTBOX, TEXT_PADDING, 5);
+    GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+    GuiSetStyle(VALUEBOX, TEXT_PADDING, 4);
+    GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+    GuiSetStyle(SPINNER, TEXT_PADDING, 4);
+    GuiSetStyle(SPINNER, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+    GuiSetStyle(STATUSBAR, TEXT_PADDING, 6);
+    GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
+
+    // Initialize extended property values
+    // NOTE: By default, extended property values are initialized to 0
+    GuiSetStyle(DEFAULT, TEXT_SIZE, 10);                // DEFAULT, shared by all controls
+    GuiSetStyle(DEFAULT, TEXT_SPACING, 1);              // DEFAULT, shared by all controls
+    GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff);       // DEFAULT specific property
+    GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
+    GuiSetStyle(TOGGLE, GROUP_PADDING, 2);
+    GuiSetStyle(SLIDER, SLIDER_WIDTH, 15);
+    GuiSetStyle(SLIDER, SLIDER_PADDING, 1);
+    GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1);
+    GuiSetStyle(CHECKBOX, CHECK_PADDING, 1);
+    GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 30);
+    GuiSetStyle(COMBOBOX, COMBO_BUTTON_PADDING, 2);
+    GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
+    GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING, 2);
+    GuiSetStyle(TEXTBOX, TEXT_LINES_PADDING, 5);
+    GuiSetStyle(TEXTBOX, TEXT_INNER_PADDING, 4);
+    GuiSetStyle(TEXTBOX, COLOR_SELECTED_FG, 0xf0fffeff);
+    GuiSetStyle(TEXTBOX, COLOR_SELECTED_BG, 0x839affe0);
+    GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 20);
+    GuiSetStyle(SPINNER, SPIN_BUTTON_PADDING, 2);
+    GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
+    GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
+    GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6);
+    GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0);
+    GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16);
+    GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0);
+    GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 10);
+    GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 0x1e);
+    GuiSetStyle(LISTVIEW, LIST_ITEMS_PADDING, 2);
+    GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 10);
+    GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE);
+    GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 6);
+    GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 0x14);
+    GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 0xa);
+    GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 6);
+    GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2);
+
+    guiFont = GetFontDefault();     // Initialize default font
+}
+
+// Get text with icon id prepended
+// NOTE: Useful to add icons by name id (enum) instead of
+// a number that can change between ricon versions
+const char *GuiIconText(int iconId, const char *text)
+{
+#if defined(RAYGUI_SUPPORT_ICONS)
+    static char buffer[1024] = { 0 };
+    memset(buffer, 0, 1024);
+
+    sprintf(buffer, "#%03i#", iconId);
+
+    if (text != NULL)
+    {
+        for (int i = 5; i < 1024; i++)
+        {
+            buffer[i] = text[i - 5];
+            if (text[i - 5] == '\0') break;
+        }
+    }
+
+    return buffer;
+#else
+    return NULL;
+#endif
+}
+
+#if defined(RAYGUI_SUPPORT_ICONS)
+
+// Get full icons data pointer
+unsigned int *GuiGetIcons(void) { return guiIcons; }
+
+// Load raygui icons file (.rgi)
+// NOTE: In case nameIds are required, they can be requested with loadIconsName,
+// they are returned as a guiIconsName[iconsCount][RICON_MAX_NAME_LENGTH],
+// guiIconsName[]][] memory should be manually freed!
+char **GuiLoadIcons(const char *fileName, bool loadIconsName)
+{
+    // Style File Structure (.rgi)
+    // ------------------------------------------------------
+    // Offset  | Size    | Type       | Description
+    // ------------------------------------------------------
+    // 0       | 4       | char       | Signature: "rGI "
+    // 4       | 2       | short      | Version: 100
+    // 6       | 2       | short      | reserved
+    
+    // 8       | 2       | short      | Num icons (N)
+    // 10      | 2       | short      | Icons size (Options: 16, 32, 64) (S)
+
+    // Icons name id (32 bytes per name id)
+    // foreach (icon)
+    // {
+    //   12+32*i  | 32   | char       | Icon NameId
+    // }
+    
+    // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size)
+    // S*S pixels/32bit per unsigned int = K unsigned int per icon
+    // foreach (icon)
+    // {
+    //   ...   | K       | unsigned int | Icon Data
+    // }
+
+    FILE *rgiFile = fopen(fileName, "rb");
+    
+    char **guiIconsName = NULL;
+
+    if (rgiFile != NULL)
+    {
+        char signature[5] = "";
+        short version = 0;
+        short reserved = 0;
+        short iconsCount = 0;
+        short iconsSize = 0;
+
+        fread(signature, 1, 4, rgiFile);
+        fread(&version, 1, sizeof(short), rgiFile);
+        fread(&reserved, 1, sizeof(short), rgiFile);
+        fread(&iconsCount, 1, sizeof(short), rgiFile);
+        fread(&iconsSize, 1, sizeof(short), rgiFile);
+
+        if ((signature[0] == 'r') &&
+            (signature[1] == 'G') &&
+            (signature[2] == 'I') &&
+            (signature[3] == ' '))
+        {
+            if (loadIconsName)
+            {
+                guiIconsName = (char **)RAYGUI_MALLOC(iconsCount*sizeof(char **));
+                for (int i = 0; i < iconsCount; i++)
+                {
+                    guiIconsName[i] = (char *)RAYGUI_MALLOC(RICON_MAX_NAME_LENGTH);
+                    fread(guiIconsName[i], 32, 1, rgiFile);
+                }
+            }
+
+            // Read icons data directly over guiIcons data array
+            fread(guiIcons, iconsCount*(iconsSize*iconsSize/32), sizeof(unsigned int), rgiFile);
+        }
+    
+        fclose(rgiFile);
+    }
+    
+    return guiIconsName;
+}
+
+// Draw selected icon using rectangles pixel-by-pixel
+void GuiDrawIcon(int iconId, Vector2 position, int pixelSize, Color color)
+{
+    #define BIT_CHECK(a,b) ((a) & (1<<(b)))
+
+    for (int i = 0, y = 0; i < RICON_SIZE*RICON_SIZE/32; i++)
+    {
+        for (int k = 0; k < 32; k++)
+        {
+            if (BIT_CHECK(guiIcons[iconId*RICON_DATA_ELEMENTS + i], k))
+            {
+            #if !defined(RAYGUI_STANDALONE)
+                DrawRectangle(position.x + (k%RICON_SIZE)*pixelSize, position.y + y*pixelSize, pixelSize, pixelSize, color);
+            #endif
+            }
+            
+            if ((k == 15) || (k == 31)) y++;
+        }
+    }
+}
+
+// Get icon bit data
+// NOTE: Bit data array grouped as unsigned int (ICON_SIZE*ICON_SIZE/32 elements)
+unsigned int *GuiGetIconData(int iconId)
+{
+    static unsigned int iconData[RICON_DATA_ELEMENTS] = { 0 };
+    memset(iconData, 0, RICON_DATA_ELEMENTS*sizeof(unsigned int));
+
+    if (iconId < RICON_MAX_ICONS) memcpy(iconData, &guiIcons[iconId*RICON_DATA_ELEMENTS], RICON_DATA_ELEMENTS*sizeof(unsigned int));
+    
+    return iconData;
+}
+
+// Set icon bit data
+// NOTE: Data must be provided as unsigned int array (ICON_SIZE*ICON_SIZE/32 elements)
+void GuiSetIconData(int iconId, unsigned int *data)
+{
+    if (iconId < RICON_MAX_ICONS) memcpy(&guiIcons[iconId*RICON_DATA_ELEMENTS], data, RICON_DATA_ELEMENTS*sizeof(unsigned int));
+}
+
+// Set icon pixel value
+void GuiSetIconPixel(int iconId, int x, int y)
+{
+    #define BIT_SET(a,b)   ((a) |= (1<<(b)))
+    
+    // This logic works for any RICON_SIZE pixels icons,
+    // For example, in case of 16x16 pixels, every 2 lines fit in one unsigned int data element
+    BIT_SET(guiIcons[iconId*RICON_DATA_ELEMENTS + y/(sizeof(unsigned int)*8/RICON_SIZE)], x + (y%(sizeof(unsigned int)*8/RICON_SIZE)*RICON_SIZE));
+}
+
+// Clear icon pixel value
+void GuiClearIconPixel(int iconId, int x, int y)
+{
+    #define BIT_CLEAR(a,b) ((a) &= ~((1)<<(b)))
+
+    // This logic works for any RICON_SIZE pixels icons,
+    // For example, in case of 16x16 pixels, every 2 lines fit in one unsigned int data element
+    BIT_CLEAR(guiIcons[iconId*RICON_DATA_ELEMENTS + y/(sizeof(unsigned int)*8/RICON_SIZE)], x + (y%(sizeof(unsigned int)*8/RICON_SIZE)*RICON_SIZE));
+}
+
+// Check icon pixel value 
+bool GuiCheckIconPixel(int iconId, int x, int y)
+{
+    #define BIT_CHECK(a,b) ((a) & (1<<(b)))
+
+    return (BIT_CHECK(guiIcons[iconId*8 + y/2], x + (y%2*16)));
+}
+#endif      // RAYGUI_SUPPORT_ICONS
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
+// Split controls text into multiple strings
+// Also check for multiple columns (required by GuiToggleGroup())
+static const char **GuiTextSplit(const char *text, int *count, int *textRow)
+{
+    // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
+    // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
+    // all used memory is static... it has some limitations:
+    //      1. Maximum number of possible split strings is set by TEXTSPLIT_MAX_TEXT_ELEMENTS
+    //      2. Maximum size of text to split is TEXTSPLIT_MAX_TEXT_LENGTH
+    // NOTE: Those definitions could be externally provided if required
+
+    #if !defined(TEXTSPLIT_MAX_TEXT_LENGTH)
+        #define TEXTSPLIT_MAX_TEXT_LENGTH      1024
+    #endif
+
+    #if !defined(TEXTSPLIT_MAX_TEXT_ELEMENTS)
+        #define TEXTSPLIT_MAX_TEXT_ELEMENTS     128
+    #endif
+
+    static const char *result[TEXTSPLIT_MAX_TEXT_ELEMENTS] = { NULL };
+    static char buffer[TEXTSPLIT_MAX_TEXT_LENGTH] = { 0 };
+    memset(buffer, 0, TEXTSPLIT_MAX_TEXT_LENGTH);
+
+    result[0] = buffer;
+    int counter = 1;
+
+    if (textRow != NULL) textRow[0] = 0;
+
+    // Count how many substrings we have on text and point to every one
+    for (int i = 0; i < TEXTSPLIT_MAX_TEXT_LENGTH; i++)
+    {
+        buffer[i] = text[i];
+        if (buffer[i] == '\0') break;
+        else if ((buffer[i] == ';') || (buffer[i] == '\n'))
+        {
+            result[counter] = buffer + i + 1;
+
+            if (textRow != NULL)
+            {
+                if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1;
+                else textRow[counter] = textRow[counter - 1];
+            }
+
+            buffer[i] = '\0';   // Set an end of string at this point
+
+            counter++;
+            if (counter == TEXTSPLIT_MAX_TEXT_ELEMENTS) break;
+        }
+    }
+
+    *count = counter;
+
+    return result;
+}
+
+// Convert color data from RGB to HSV
+// NOTE: Color data should be passed normalized
+static Vector3 ConvertRGBtoHSV(Vector3 rgb)
+{
+    Vector3 hsv = { 0 };
+    float min = 0.0f;
+    float max = 0.0f;
+    float delta = 0.0f;
+
+    min = (rgb.x < rgb.y)? rgb.x : rgb.y;
+    min = (min < rgb.z)? min  : rgb.z;
+
+    max = (rgb.x > rgb.y)? rgb.x : rgb.y;
+    max = (max > rgb.z)? max  : rgb.z;
+
+    hsv.z = max;            // Value
+    delta = max - min;
+
+    if (delta < 0.00001f)
+    {
+        hsv.y = 0.0f;
+        hsv.x = 0.0f;       // Undefined, maybe NAN?
+        return hsv;
+    }
+
+    if (max > 0.0f)
+    {
+        // NOTE: If max is 0, this divide would cause a crash
+        hsv.y = (delta/max);    // Saturation
+    }
+    else
+    {
+        // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
+        hsv.y = 0.0f;
+        hsv.x = 0.0f;        // Undefined, maybe NAN?
+        return hsv;
+    }
+
+    // NOTE: Comparing float values could not work properly
+    if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta;    // Between yellow & magenta
+    else
+    {
+        if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta;  // Between cyan & yellow
+        else hsv.x = 4.0f + (rgb.x - rgb.y)/delta;      // Between magenta & cyan
+    }
+
+    hsv.x *= 60.0f;     // Convert to degrees
+
+    if (hsv.x < 0.0f) hsv.x += 360.0f;
+
+    return hsv;
+}
+
+// Convert color data from HSV to RGB
+// NOTE: Color data should be passed normalized
+static Vector3 ConvertHSVtoRGB(Vector3 hsv)
+{
+    Vector3 rgb = { 0 };
+    float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
+    long i = 0;
+
+    // NOTE: Comparing float values could not work properly
+    if (hsv.y <= 0.0f)
+    {
+        rgb.x = hsv.z;
+        rgb.y = hsv.z;
+        rgb.z = hsv.z;
+        return rgb;
+    }
+
+    hh = hsv.x;
+    if (hh >= 360.0f) hh = 0.0f;
+    hh /= 60.0f;
+
+    i = (long)hh;
+    ff = hh - i;
+    p = hsv.z*(1.0f - hsv.y);
+    q = hsv.z*(1.0f - (hsv.y*ff));
+    t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
+
+    switch (i)
+    {
+        case 0:
+        {
+            rgb.x = hsv.z;
+            rgb.y = t;
+            rgb.z = p;
+        } break;
+        case 1:
+        {
+            rgb.x = q;
+            rgb.y = hsv.z;
+            rgb.z = p;
+        } break;
+        case 2:
+        {
+            rgb.x = p;
+            rgb.y = hsv.z;
+            rgb.z = t;
+        } break;
+        case 3:
+        {
+            rgb.x = p;
+            rgb.y = q;
+            rgb.z = hsv.z;
+        } break;
+        case 4:
+        {
+            rgb.x = t;
+            rgb.y = p;
+            rgb.z = hsv.z;
+        } break;
+        case 5:
+        default:
+        {
+            rgb.x = hsv.z;
+            rgb.y = p;
+            rgb.z = q;
+        } break;
+    }
+
+    return rgb;
+}
+
+#if defined(RAYGUI_STANDALONE)
+// Returns a Color struct from hexadecimal value
+static Color GetColor(int hexValue)
+{
+    Color color;
+
+    color.r = (unsigned char)(hexValue >> 24) & 0xFF;
+    color.g = (unsigned char)(hexValue >> 16) & 0xFF;
+    color.b = (unsigned char)(hexValue >> 8) & 0xFF;
+    color.a = (unsigned char)hexValue & 0xFF;
+
+    return color;
+}
+
+// Returns hexadecimal value for a Color
+static int ColorToInt(Color color)
+{
+    return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
+}
+
+// Check if point is inside rectangle
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
+{
+    bool collision = false;
+
+    if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) &&
+        (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
+
+    return collision;
+}
+
+// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+static Color Fade(Color color, float alpha)
+{
+    if (alpha < 0.0f) alpha = 0.0f;
+    else if (alpha > 1.0f) alpha = 1.0f;
+
+    return RAYGUI_CLITERAL(Color){ color.r, color.g, color.b, (unsigned char)(255.0f*alpha) };
+}
+
+// Formatting of text with variables to 'embed'
+static const char *TextFormat(const char *text, ...)
+{
+    #define MAX_FORMATTEXT_LENGTH   64
+
+    static char buffer[MAX_FORMATTEXT_LENGTH];
+
+    va_list args;
+    va_start(args, text);
+    vsprintf(buffer, text, args);
+    va_end(args);
+
+    return buffer;
+}
+
+// Draw rectangle filled with color
+static void DrawRectangleRec(Rectangle rec, Color color)
+{
+    DrawRectangle(rec.x, rec.y, rec.width, rec.height, color);
+}
+
+// Draw rectangle border lines with color
+static void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color)
+{
+    DrawRectangle(rec.x, rec.y, rec.width, lineThick, color);
+    DrawRectangle(rec.x, rec.y + lineThick, lineThick, rec.height - 2*lineThick, color);
+    DrawRectangle(rec.x + rec.width - lineThick, rec.y + lineThick, lineThick, rec.height - 2*lineThick, color);
+    DrawRectangle(rec.x, rec.y + rec.height - lineThick, rec.width, lineThick, color);
+}
+
+// Draw rectangle with vertical gradient fill color
+// NOTE: This function is only used by GuiColorPicker()
+static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
+{
+    Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height };
+    DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
+}
+
+#define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH    1024        // Size of static buffer: TextSplit()
+#define TEXTSPLIT_MAX_SUBSTRINGS_COUNT       128        // Size of static pointers array: TextSplit()
+
+
+// Split string into multiple strings
+const char **TextSplit(const char *text, char delimiter, int *count)
+{
+    // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
+    // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
+    // all used memory is static... it has some limitations:
+    //      1. Maximum number of possible split strings is set by TEXTSPLIT_MAX_SUBSTRINGS_COUNT
+    //      2. Maximum size of text to split is TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
+
+    static const char *result[TEXTSPLIT_MAX_SUBSTRINGS_COUNT] = { NULL };
+    static char buffer[TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH] = { 0 };
+    memset(buffer, 0, TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH);
+
+    result[0] = buffer;
+    int counter = 0;
+
+    if (text != NULL)
+    {
+        counter = 1;
+
+        // Count how many substrings we have on text and point to every one
+        for (int i = 0; i < TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH; i++)
+        {
+            buffer[i] = text[i];
+            if (buffer[i] == '\0') break;
+            else if (buffer[i] == delimiter)
+            {
+                buffer[i] = '\0';   // Set an end of string at this point
+                result[counter] = buffer + i + 1;
+                counter++;
+
+                if (counter == TEXTSPLIT_MAX_SUBSTRINGS_COUNT) break;
+            }
+        }
+    }
+
+    *count = counter;
+    return result;
+}
+
+// Get integer value from text
+// NOTE: This function replaces atoi() [stdlib.h]
+static int TextToInteger(const char *text)
+{
+    int value = 0;
+    int sign = 1;
+
+    if ((text[0] == '+') || (text[0] == '-'))
+    {
+        if (text[0] == '-') sign = -1;
+        text++;
+    }
+  
+    for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0');
+
+    return value*sign; 
+}
+#endif      // RAYGUI_STANDALONE
+
+#endif      // RAYGUI_IMPLEMENTATION

+ 556 - 0
gui.mod/raygui/src/ricons.h

@@ -0,0 +1,556 @@
+/**********************************************************************************************
+*
+*   rIcons - Icons pack intended for tools development with raygui
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2019-2020 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#ifndef RICONS_H
+#define RICONS_H
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define RICON_MAX_ICONS         256       // Maximum number of icons
+#define RICON_SIZE               16       // Size of icons (squared)
+
+#define RICON_MAX_NAME_LENGTH    32       // Maximum length of icon name id
+
+// Icons data is defined by bit array (every bit represents one pixel)
+// Those arrays are stored as unsigned int data arrays, so every array
+// element defines 32 pixels (bits) of information
+// Number of elemens depend on RICON_SIZE (by default 16x16 pixels) 
+#define RICON_DATA_ELEMENTS   (RICON_SIZE*RICON_SIZE/32)
+
+//----------------------------------------------------------------------------------
+// Icons enumeration
+//----------------------------------------------------------------------------------
+typedef enum {
+    RICON_NONE                     = 0,
+    RICON_FOLDER_FILE_OPEN         = 1,
+    RICON_FILE_SAVE_CLASSIC        = 2,
+    RICON_FOLDER_OPEN              = 3,
+    RICON_FOLDER_SAVE              = 4,
+    RICON_FILE_OPEN                = 5,
+    RICON_FILE_SAVE                = 6,
+    RICON_FILE_EXPORT              = 7,
+    RICON_FILE_NEW                 = 8,
+    RICON_FILE_DELETE              = 9,
+    RICON_FILETYPE_TEXT            = 10,
+    RICON_FILETYPE_AUDIO           = 11,
+    RICON_FILETYPE_IMAGE           = 12,
+    RICON_FILETYPE_PLAY            = 13,
+    RICON_FILETYPE_VIDEO           = 14,
+    RICON_FILETYPE_INFO            = 15,
+    RICON_FILE_COPY                = 16,
+    RICON_FILE_CUT                 = 17,
+    RICON_FILE_PASTE               = 18,
+    RICON_CURSOR_HAND              = 19,
+    RICON_CURSOR_POINTER           = 20,
+    RICON_CURSOR_CLASSIC           = 21,
+    RICON_PENCIL                   = 22,
+    RICON_PENCIL_BIG               = 23,
+    RICON_BRUSH_CLASSIC            = 24,
+    RICON_BRUSH_PAINTER            = 25,
+    RICON_WATER_DROP               = 26,
+    RICON_COLOR_PICKER             = 27,
+    RICON_RUBBER                   = 28,
+    RICON_COLOR_BUCKET             = 29,
+    RICON_TEXT_T                   = 30,
+    RICON_TEXT_A                   = 31,
+    RICON_SCALE                    = 32,
+    RICON_RESIZE                   = 33,
+    RICON_FILTER_POINT             = 34,
+    RICON_FILTER_BILINEAR          = 35,
+    RICON_CROP                     = 36,
+    RICON_CROP_ALPHA               = 37,
+    RICON_SQUARE_TOGGLE            = 38,
+    RICON_SIMMETRY                 = 39,
+    RICON_SIMMETRY_HORIZONTAL      = 40,
+    RICON_SIMMETRY_VERTICAL        = 41,
+    RICON_LENS                     = 42,
+    RICON_LENS_BIG                 = 43,
+    RICON_EYE_ON                   = 44,
+    RICON_EYE_OFF                  = 45,
+    RICON_FILTER_TOP               = 46,
+    RICON_FILTER                   = 47,
+    RICON_TARGET_POINT             = 48,
+    RICON_TARGET_SMALL             = 49,
+    RICON_TARGET_BIG               = 50,
+    RICON_TARGET_MOVE              = 51,
+    RICON_CURSOR_MOVE              = 52,
+    RICON_CURSOR_SCALE             = 53,
+    RICON_CURSOR_SCALE_RIGHT       = 54,
+    RICON_CURSOR_SCALE_LEFT        = 55,
+    RICON_UNDO                     = 56,
+    RICON_REDO                     = 57,
+    RICON_REREDO                   = 58,
+    RICON_MUTATE                   = 59,
+    RICON_ROTATE                   = 60,
+    RICON_REPEAT                   = 61,
+    RICON_SHUFFLE                  = 62,
+    RICON_EMPTYBOX                 = 63,
+    RICON_TARGET                   = 64,
+    RICON_TARGET_SMALL_FILL        = 65,
+    RICON_TARGET_BIG_FILL          = 66,
+    RICON_TARGET_MOVE_FILL         = 67,
+    RICON_CURSOR_MOVE_FILL         = 68,
+    RICON_CURSOR_SCALE_FILL        = 69,
+    RICON_CURSOR_SCALE_RIGHT_FILL  = 70,
+    RICON_CURSOR_SCALE_LEFT_FILL   = 71,
+    RICON_UNDO_FILL                = 72,
+    RICON_REDO_FILL                = 73,
+    RICON_REREDO_FILL              = 74,
+    RICON_MUTATE_FILL              = 75,
+    RICON_ROTATE_FILL              = 76,
+    RICON_REPEAT_FILL              = 77,
+    RICON_SHUFFLE_FILL             = 78,
+    RICON_EMPTYBOX_SMALL           = 79,
+    RICON_BOX                      = 80,
+    RICON_BOX_TOP                  = 81,
+    RICON_BOX_TOP_RIGHT            = 82,
+    RICON_BOX_RIGHT                = 83,
+    RICON_BOX_BOTTOM_RIGHT         = 84,
+    RICON_BOX_BOTTOM               = 85,
+    RICON_BOX_BOTTOM_LEFT          = 86,
+    RICON_BOX_LEFT                 = 87,
+    RICON_BOX_TOP_LEFT             = 88,
+    RICON_BOX_CENTER               = 89,
+    RICON_BOX_CIRCLE_MASK          = 90,
+    RICON_POT                      = 91,
+    RICON_ALPHA_MULTIPLY           = 92,
+    RICON_ALPHA_CLEAR              = 93,
+    RICON_DITHERING                = 94,
+    RICON_MIPMAPS                  = 95,
+    RICON_BOX_GRID                 = 96,
+    RICON_GRID                     = 97,
+    RICON_BOX_CORNERS_SMALL        = 98,
+    RICON_BOX_CORNERS_BIG          = 99,
+    RICON_FOUR_BOXES               = 100,
+    RICON_GRID_FILL                = 101,
+    RICON_BOX_MULTISIZE            = 102,
+    RICON_ZOOM_SMALL               = 103,
+    RICON_ZOOM_MEDIUM              = 104,
+    RICON_ZOOM_BIG                 = 105,
+    RICON_ZOOM_ALL                 = 106,
+    RICON_ZOOM_CENTER              = 107,
+    RICON_BOX_DOTS_SMALL           = 108,
+    RICON_BOX_DOTS_BIG             = 109,
+    RICON_BOX_CONCENTRIC           = 110,
+    RICON_BOX_GRID_BIG             = 111,
+    RICON_OK_TICK                  = 112,
+    RICON_CROSS                    = 113,
+    RICON_ARROW_LEFT               = 114,
+    RICON_ARROW_RIGHT              = 115,
+    RICON_ARROW_BOTTOM             = 116,
+    RICON_ARROW_TOP                = 117,
+    RICON_ARROW_LEFT_FILL          = 118,
+    RICON_ARROW_RIGHT_FILL         = 119,
+    RICON_ARROW_BOTTOM_FILL        = 120,
+    RICON_ARROW_TOP_FILL           = 121,
+    RICON_AUDIO                    = 122,
+    RICON_FX                       = 123,
+    RICON_WAVE                     = 124,
+    RICON_WAVE_SINUS               = 125,
+    RICON_WAVE_SQUARE              = 126,
+    RICON_WAVE_TRIANGULAR          = 127,
+    RICON_CROSS_SMALL              = 128,
+    RICON_PLAYER_PREVIOUS          = 129,
+    RICON_PLAYER_PLAY_BACK         = 130,
+    RICON_PLAYER_PLAY              = 131,
+    RICON_PLAYER_PAUSE             = 132,
+    RICON_PLAYER_STOP              = 133,
+    RICON_PLAYER_NEXT              = 134,
+    RICON_PLAYER_RECORD            = 135,
+    RICON_MAGNET                   = 136,
+    RICON_LOCK_CLOSE               = 137,
+    RICON_LOCK_OPEN                = 138,
+    RICON_CLOCK                    = 139,
+    RICON_TOOLS                    = 140,
+    RICON_GEAR                     = 141,
+    RICON_GEAR_BIG                 = 142,
+    RICON_BIN                      = 143,
+    RICON_HAND_POINTER             = 144,
+    RICON_LASER                    = 145,
+    RICON_COIN                     = 146,
+    RICON_EXPLOSION                = 147,
+    RICON_1UP                      = 148,
+    RICON_PLAYER                   = 149,
+    RICON_PLAYER_JUMP              = 150,
+    RICON_KEY                      = 151,
+    RICON_DEMON                    = 152,
+    RICON_TEXT_POPUP               = 153,
+    RICON_GEAR_EX                  = 154,
+    RICON_CRACK                    = 155,
+    RICON_CRACK_POINTS             = 156,
+    RICON_STAR                     = 157,
+    RICON_DOOR                     = 158,
+    RICON_EXIT                     = 159,
+    RICON_MODE_2D                  = 160,
+    RICON_MODE_3D                  = 161,
+    RICON_CUBE                     = 162,
+    RICON_CUBE_FACE_TOP            = 163,
+    RICON_CUBE_FACE_LEFT           = 164,
+    RICON_CUBE_FACE_FRONT          = 165,
+    RICON_CUBE_FACE_BOTTOM         = 166,
+    RICON_CUBE_FACE_RIGHT          = 167,
+    RICON_CUBE_FACE_BACK           = 168,
+    RICON_CAMERA                   = 169,
+    RICON_SPECIAL                  = 170,
+    RICON_LINK_NET                 = 171,
+    RICON_LINK_BOXES               = 172,
+    RICON_LINK_MULTI               = 173,
+    RICON_LINK                     = 174,
+    RICON_LINK_BROKE               = 175,
+    RICON_TEXT_NOTES               = 176,
+    RICON_NOTEBOOK                 = 177,
+    RICON_SUITCASE                 = 178,
+    RICON_SUITCASE_ZIP             = 179,
+    RICON_MAILBOX                  = 180,
+    RICON_MONITOR                  = 181,
+    RICON_PRINTER                  = 182,
+    RICON_PHOTO_CAMERA             = 183,
+    RICON_PHOTO_CAMERA_FLASH       = 184,
+    RICON_HOUSE                    = 185,
+    RICON_HEART                    = 186,
+    RICON_CORNER                   = 187,
+    RICON_VERTICAL_BARS            = 188,
+    RICON_VERTICAL_BARS_FILL       = 189,
+    RICON_LIFE_BARS                = 190,
+    RICON_INFO                     = 191,
+    RICON_CROSSLINE                = 192,
+    RICON_HELP                     = 193,
+    RICON_FILETYPE_ALPHA           = 194,
+    RICON_FILETYPE_HOME            = 195,
+    RICON_LAYERS_VISIBLE           = 196,
+    RICON_LAYERS                   = 197,
+    RICON_WINDOW                   = 198,
+    RICON_HIDPI                    = 199,
+    RICON_200                      = 200,
+    RICON_201                      = 201,
+    RICON_202                      = 202,
+    RICON_203                      = 203,
+    RICON_204                      = 204,
+    RICON_205                      = 205,
+    RICON_206                      = 206,
+    RICON_207                      = 207,
+    RICON_208                      = 208,
+    RICON_209                      = 209,
+    RICON_210                      = 210,
+    RICON_211                      = 211,
+    RICON_212                      = 212,
+    RICON_213                      = 213,
+    RICON_214                      = 214,
+    RICON_215                      = 215,
+    RICON_216                      = 216,
+    RICON_217                      = 217,
+    RICON_218                      = 218,
+    RICON_219                      = 219,
+    RICON_220                      = 220,
+    RICON_221                      = 221,
+    RICON_222                      = 222,
+    RICON_223                      = 223,
+    RICON_224                      = 224,
+    RICON_225                      = 225,
+    RICON_226                      = 226,
+    RICON_227                      = 227,
+    RICON_228                      = 228,
+    RICON_229                      = 229,
+    RICON_230                      = 230,
+    RICON_231                      = 231,
+    RICON_232                      = 232,
+    RICON_233                      = 233,
+    RICON_234                      = 234,
+    RICON_235                      = 235,
+    RICON_236                      = 236,
+    RICON_237                      = 237,
+    RICON_238                      = 238,
+    RICON_239                      = 239,
+    RICON_240                      = 240,
+    RICON_241                      = 241,
+    RICON_242                      = 242,
+    RICON_243                      = 243,
+    RICON_244                      = 244,
+    RICON_245                      = 245,
+    RICON_246                      = 246,
+    RICON_247                      = 247,
+    RICON_248                      = 248,
+    RICON_249                      = 249,
+    RICON_250                      = 250,
+    RICON_251                      = 251,
+    RICON_252                      = 252,
+    RICON_253                      = 253,
+    RICON_254                      = 254,
+    RICON_255                      = 255,
+} guiIconName;
+
+#endif  // RICONS_H
+
+#if defined(RICONS_IMPLEMENTATION)
+//----------------------------------------------------------------------------------
+// Icons data (allocated on heap by default)
+// NOTE: A new icon set could be loaded over this array using GuiLoadIcons(),
+// just note that loaded icons set must be same RICON_SIZE
+//----------------------------------------------------------------------------------
+static unsigned int guiIcons[RICON_MAX_ICONS*RICON_DATA_ELEMENTS] = {
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_NONE
+    0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe,     // RICON_FOLDER_FILE_OPEN
+    0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe,     // RICON_FILE_SAVE_CLASSIC
+    0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100,     // RICON_FOLDER_OPEN
+    0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000,     // RICON_FOLDER_SAVE
+    0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc,     // RICON_FILE_OPEN
+    0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc,     // RICON_FILE_SAVE
+    0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc,     // RICON_FILE_EXPORT
+    0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc,     // RICON_FILE_NEW
+    0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc,     // RICON_FILE_DELETE
+    0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc,     // RICON_FILETYPE_TEXT
+    0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc,     // RICON_FILETYPE_AUDIO
+    0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc,     // RICON_FILETYPE_IMAGE
+    0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc,     // RICON_FILETYPE_PLAY
+    0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4,     // RICON_FILETYPE_VIDEO
+    0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc,     // RICON_FILETYPE_INFO
+    0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0,     // RICON_FILE_COPY
+    0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000,     // RICON_FILE_CUT
+    0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0,     // RICON_FILE_PASTE
+    0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_CURSOR_HAND
+    0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000,     // RICON_CURSOR_POINTER
+    0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000,     // RICON_CURSOR_CLASSIC
+    0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000,     // RICON_PENCIL
+    0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000,     // RICON_PENCIL_BIG
+    0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8,     // RICON_BRUSH_CLASSIC
+    0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080,     // RICON_BRUSH_PAINTER
+    0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000,     // RICON_WATER_DROP
+    0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000,     // RICON_COLOR_PICKER
+    0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000,     // RICON_RUBBER
+    0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040,     // RICON_COLOR_BUCKET
+    0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000,     // RICON_TEXT_T
+    0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f,     // RICON_TEXT_A
+    0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e,     // RICON_SCALE
+    0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe,     // RICON_RESIZE
+    0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000,     // RICON_FILTER_POINT
+    0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000,     // RICON_FILTER_BILINEAR
+    0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002,     // RICON_CROP
+    0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000,     // RICON_CROP_ALPHA
+    0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002,     // RICON_SQUARE_TOGGLE
+    0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000,     // RICON_SIMMETRY
+    0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100,     // RICON_SIMMETRY_HORIZONTAL
+    0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180,     // RICON_SIMMETRY_VERTICAL
+    0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000,     // RICON_LENS
+    0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000,     // RICON_LENS_BIG
+    0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000,     // RICON_EYE_ON
+    0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000,     // RICON_EYE_OFF
+    0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100,     // RICON_FILTER_TOP
+    0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0,     // RICON_FILTER
+    0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000,     // RICON_TARGET_POINT
+    0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000,     // RICON_TARGET_SMALL
+    0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000,     // RICON_TARGET_BIG
+    0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280,     // RICON_TARGET_MOVE
+    0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280,     // RICON_CURSOR_MOVE
+    0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e,     // RICON_CURSOR_SCALE
+    0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000,     // RICON_CURSOR_SCALE_RIGHT
+    0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000,     // RICON_CURSOR_SCALE_LEFT
+    0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000,     // RICON_UNDO
+    0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000,     // RICON_REDO
+    0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000,     // RICON_REREDO
+    0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000,     // RICON_MUTATE
+    0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020,     // RICON_ROTATE
+    0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000,     // RICON_REPEAT
+    0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000,     // RICON_SHUFFLE
+    0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe,     // RICON_EMPTYBOX
+    0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000,     // RICON_TARGET
+    0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000,     // RICON_TARGET_SMALL_FILL
+    0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000,     // RICON_TARGET_BIG_FILL
+    0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380,     // RICON_TARGET_MOVE_FILL
+    0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380,     // RICON_CURSOR_MOVE_FILL
+    0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e,     // RICON_CURSOR_SCALE_FILL
+    0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000,     // RICON_CURSOR_SCALE_RIGHT
+    0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000,     // RICON_CURSOR_SCALE_LEFT
+    0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000,     // RICON_UNDO_FILL
+    0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000,     // RICON_REDO_FILL
+    0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000,     // RICON_REREDO_FILL
+    0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000,     // RICON_MUTATE_FILL
+    0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020,     // RICON_ROTATE_FILL
+    0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000,     // RICON_REPEAT_FILL
+    0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000,     // RICON_SHUFFLE_FILL
+    0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000,     // RICON_EMPTYBOX_SMALL
+    0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX
+    0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_TOP
+    0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_TOP_RIGHT
+    0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_RIGHT
+    0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000,     // RICON_BOX_BOTTOM_RIGHT
+    0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000,     // RICON_BOX_BOTTOM
+    0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000,     // RICON_BOX_BOTTOM_LEFT
+    0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_LEFT
+    0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_TOP_LEFT
+    0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000,     // RICON_BOX_CIRCLE_MASK
+    0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe,     // RICON_BOX_CENTER
+    0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff,     // RICON_POT
+    0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe,     // RICON_ALPHA_MULTIPLY
+    0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe,     // RICON_ALPHA_CLEAR
+    0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe,     // RICON_DITHERING
+    0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0,     // RICON_MIPMAPS
+    0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000,     // RICON_BOX_GRID
+    0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248,     // RICON_GRID
+    0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000,     // RICON_BOX_CORNERS_SMALL
+    0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e,     // RICON_BOX_CORNERS_BIG
+    0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000,     // RICON_FOUR_BOXES
+    0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000,     // RICON_GRID_FILL
+    0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e,     // RICON_BOX_MULTISIZE
+    0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e,     // RICON_ZOOM_SMALL
+    0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e,     // RICON_ZOOM_MEDIUM
+    0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e,     // RICON_ZOOM_BIG
+    0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e,     // RICON_ZOOM_ALL
+    0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000,     // RICON_ZOOM_CENTER
+    0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000,     // RICON_BOX_DOTS_SMALL
+    0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000,     // RICON_BOX_DOTS_BIG
+    0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe,     // RICON_BOX_CONCENTRIC
+    0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000,     // RICON_BOX_GRID_BIG
+    0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000,     // RICON_OK_TICK
+    0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000,     // RICON_CROSS
+    0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000,     // RICON_ARROW_LEFT
+    0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000,     // RICON_ARROW_RIGHT
+    0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000,     // RICON_ARROW_BOTTOM
+    0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000,     // RICON_ARROW_TOP
+    0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000,     // RICON_ARROW_LEFT_FILL
+    0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000,     // RICON_ARROW_RIGHT_FILL
+    0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000,     // RICON_ARROW_BOTTOM_FILL
+    0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000,     // RICON_ARROW_TOP_FILL
+    0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000,     // RICON_AUDIO
+    0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000,     // RICON_FX
+    0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000,     // RICON_WAVE
+    0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000,     // RICON_WAVE_SINUS
+    0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000,     // RICON_WAVE_SQUARE
+    0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000,     // RICON_WAVE_TRIANGULAR
+    0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000,     // RICON_CROSS_SMALL
+    0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000,     // RICON_PLAYER_PREVIOUS
+    0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000,     // RICON_PLAYER_PLAY_BACK
+    0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000,     // RICON_PLAYER_PLAY
+    0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000,     // RICON_PLAYER_PAUSE
+    0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000,     // RICON_PLAYER_STOP
+    0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000,     // RICON_PLAYER_NEXT
+    0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000,     // RICON_PLAYER_RECORD
+    0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000,     // RICON_MAGNET
+    0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000,     // RICON_LOCK_CLOSE
+    0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000,     // RICON_LOCK_OPEN
+    0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770,     // RICON_CLOCK
+    0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70,     // RICON_TOOLS
+    0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180,     // RICON_GEAR
+    0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180,     // RICON_GEAR_BIG
+    0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8,     // RICON_BIN
+    0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000,     // RICON_HAND_POINTER
+    0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000,     // RICON_LASER
+    0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000,     // RICON_COIN
+    0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000,     // RICON_EXPLOSION
+    0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000,     // RICON_1UP
+    0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240,     // RICON_PLAYER
+    0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000,     // RICON_PLAYER_JUMP
+    0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0,     // RICON_KEY
+    0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0,     // RICON_DEMON
+    0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000,     // RICON_TEXT_POPUP
+    0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000,     // RICON_GEAR_EX
+    0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000,     // RICON_CRACK
+    0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000,     // RICON_CRACK_POINTS
+    0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808,     // RICON_STAR
+    0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8,     // RICON_DOOR
+    0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0,     // RICON_EXIT
+    0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000,     // RICON_MODE_2D
+    0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000,     // RICON_MODE_3D
+    0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe,     // RICON_CUBE
+    0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe,     // RICON_CUBE_FACE_TOP
+    0x7fe00000, 0x50386030, 0x47fe483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe,     // RICON_CUBE_FACE_LEFT
+    0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe,     // RICON_CUBE_FACE_FRONT
+    0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3ff27fe2, 0x0ffe1ffa, 0x000007fe,     // RICON_CUBE_FACE_BOTTOM
+    0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe,     // RICON_CUBE_FACE_RIGHT
+    0x7fe00000, 0x7fe87ff0, 0x7ffe7fe4, 0x7fe27fe2, 0x7fe27fe2, 0x24127fe2, 0x0c06140a, 0x000007fe,     // RICON_CUBE_FACE_BACK
+    0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000,     // RICON_CAMERA
+    0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000,     // RICON_SPECIAL
+    0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800,     // RICON_LINK_NET
+    0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00,     // RICON_LINK_BOXES
+    0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000,     // RICON_LINK_MULTI
+    0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00,     // RICON_LINK
+    0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00,     // RICON_LINK_BROKE
+    0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc,     // RICON_TEXT_NOTES
+    0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc,     // RICON_NOTEBOOK
+    0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000,     // RICON_SUITCASE
+    0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000,     // RICON_SUITCASE_ZIP
+    0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000,     // RICON_MAILBOX
+    0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000,     // RICON_MONITOR
+    0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000,     // RICON_PRINTER
+    0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000,     // RICON_PHOTO_CAMERA
+    0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000,     // RICON_PHOTO_CAMERA_FLASH
+    0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000,     // RICON_HOUSE
+    0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000,     // RICON_HEART
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000,     // RICON_CORNER
+    0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000,     // RICON_VERTICAL_BARS
+    0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000,     // RICON_VERTICAL_BARS_FILL
+    0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000,     // RICON_LIFE_BARS
+    0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc,     // RICON_INFO
+    0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002,     // RICON_CROSSLINE
+    0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000,     // RICON_HELP
+    0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc,     // RICON_FILETYPE_ALPHA
+    0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc,     // RICON_FILETYPE_HOME
+    0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0,     // RICON_LAYERS_VISIBLE
+    0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0,     // RICON_LAYERS
+    0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000,     // RICON_WINDOW
+    0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000,     // RICON_HIDPI
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_200
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_201
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_202
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_203
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_204
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_205
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_206
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_207
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_208
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_209
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_210
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_211
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_212
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_213
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_214
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_215
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_216
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_217
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_218
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_219
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_220
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_221
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_222
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_223
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_224
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_225
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_226
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_227
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_228
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_229
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_230
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_231
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_232
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_233
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_234
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_235
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_236
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_237
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_238
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_239
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_240
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_241
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_242
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_243
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_244
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_245
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_246
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_247
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_248
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_249
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_250
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_251
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_252
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_253
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_254
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,     // RICON_255
+};
+#endif      // RICONS_IMPLEMENTATION

+ 36 - 0
gui.mod/raygui/styles/README.md

@@ -0,0 +1,36 @@
+## raygui styles
+
+`raygui` comes with **8 custom styles** carefully designed for the best visual experience. Those styles have been created using [rGuiStyler](https://raylibtech.itch.io/rguistyler) tool and they complement internal [default style](default), always available by `raygui`.
+
+To use those styles with your `raygui` development, just need to call `GuiLoadStyle()` function at initialization, passing the `.rgs` file to load. Note that most of those styles depend on custom fonts that must be available together with the `.rgs` file.
+
+Here it is a quick overview of those styles, you can navigate to each directory for additional information.
+
+#### style: [default](default)
+![default style](default/style_table.png)
+
+#### style: [ashes](ashes)
+![ashes style](ashes/style_table.png)
+
+#### style: [bluish](bluish)
+![bluish style](bluish/style_table.png)
+
+#### style: [candy](candy)
+![candy style](candy/style_table.png)
+
+#### style: [cherry](cherry)
+![cherry style](cherry/style_table.png)
+
+#### style: [cyber](cyber)
+![cyber style](cyber/style_table.png)
+
+#### style: [jungle](jungle)
+![jungle style](jungle/style_table.png)
+
+#### style: [lavanda](lavanda)
+![lavanda style](lavanda/style_table.png)
+
+#### style: [terminal](terminal)
+![terminal style](terminal/style_table.png)
+
+*NOTE: Those styles require latest raylib 2.6-dev and latest raygui 2.6-dev.*

+ 16 - 0
gui.mod/raygui/styles/ashes/README.md

@@ -0,0 +1,16 @@
+style: ashes
+-------------
+What once was life now is ashes, just as slight reminiscense covers the ground, a gray sequence of tones that reminds to a distant past.
+
+![ashes style table](style_table.png)
+
+screenshot
+-----------
+
+![ashes style screen](screenshot.png)
+
+about font
+-----------
+"V5 Loxica Lixera" font by vFive Digital (Roberto Christen).
+
+100% free font, downloaded from dafont.com: [v5loxica-lixera](https://www.dafont.com/v5loxica-lixera.font)

+ 24 - 0
gui.mod/raygui/styles/ashes/ashes.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 16 0 v5loxical.ttf
+p 00 00 0xf0f0f0ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0x868686ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0xe6e6e6ff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0x929999ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0xeaeaeaff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0x98a1a8ff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0x3f3f3fff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0xf6f6f6ff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0x414141ff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0x8b8b8bff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0x777777ff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x959595ff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x00000010    TEXT_SIZE
+p 00 17 0x00000001    TEXT_SPACING
+p 00 18 0x9dadb1ff    DEFAULT_LINE_COLOR
+p 00 19 0x6b6b6bff    DEFAULT_BACKGROUND_COLOR

+ 51 - 0
gui.mod/raygui/styles/ashes/font_readme.txt

@@ -0,0 +1,51 @@
+
+V5 Loxica
+---------------
+Instructions:
+
+
+++ Loxica (LIXERA) ++
+
+For screen use, set at 16pt.  Turn
+antialiasing off.  Set tracking to zero
+for best results.
+
+++ Loxica (ROBUSTA) ++
+
+For screen use, set at 18pt.  Turn
+antialiasing off.  Set tracking to zero
+for best results.
+
+
+Notes:
+
+1. These faces do not contain any hinting 
+information since they were built for use 
+at the sizes listed above.  Naturally, for 
+print use you are free to experiment.
+
+2. Although the intended size for _lixera_
+is 16pt (vs. 18pt for _robusta_), they share
+the same optical size (where lixera is the 
+regular weight, and robusta is the bold).
+
+3. Pronounciation: "lo-hee-ka lee-he-ra", and
+"lo-hee-ka ro-bus-ta."
+
+
+
+---------------
+Usage:  This is a free font--you may use 
+this and other V5 fonts at will.  It may not 
+be sold, altered, or improperly credited,
+however.  All I ask is that you kindly inform 
+me if you find this font useful, and where
+you've used it.
+
+Enjoy,
+
+©2000 
+Roberto Christen
[email protected]
+
+

二进制
gui.mod/raygui/styles/ashes/screenshot.png


二进制
gui.mod/raygui/styles/ashes/style_table.png


二进制
gui.mod/raygui/styles/ashes/v5loxical.ttf


+ 16 - 0
gui.mod/raygui/styles/bluish/README.md

@@ -0,0 +1,16 @@
+style: bluish
+--------------
+Like a breeze, a slight touch of color cover the clear sky, a spacious and relaxing feeling.
+
+![bluish style table](style_table.png)
+
+screenshot
+-----------
+
+![bluish style screen](screenshot.png)
+
+about font
+-----------
+"Homespun BRK" font by AEnigma (Brian Kent).
+
+100% free font, downloaded from dafont.com: [homespun-brk](https://www.dafont.com/homespun-brk.font)

+ 24 - 0
gui.mod/raygui/styles/bluish/bluish.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 10 0 homespun.ttf
+p 00 00 0x5ca6a6ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0xb4e8f3ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0x447e77ff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0x5f8792ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0xcdeff7ff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0x4c6c74ff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0x3b5b5fff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0xeaffffff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0x275057ff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0x96aaacff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0xc8d7d9ff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x8c9c9eff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x0000000a    TEXT_SIZE
+p 00 17 0x00000001    TEXT_SPACING
+p 00 18 0x84adb7ff    DEFAULT_LINE_COLOR
+p 00 19 0xe8eef1ff    DEFAULT_BACKGROUND_COLOR

+ 76 - 0
gui.mod/raygui/styles/bluish/font_readme.txt

@@ -0,0 +1,76 @@
+_______________________________
+Homespun  Created by Brian Kent
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+Thanks for Downloading Homespun.
+
+Homespun TT         [.ttf]
+Homespun     [8pt]  [.fon]
+
+
+  'homespun.fon' is a Windows Bitmap Font (.fon).  This font is best
+used at 8pt.  To use it at larger point sizes (for images), try using
+a graphics program like Photoshop, Paint Shop Pro, or the Paint
+program that comes with Windows.  Type out your text at the recommended
+point size [8pt], then resize the image.   Set the color mode to 256
+or 2 colors so the edges don't get blured when resizing, then after you
+have the text to the size that you want, then change back to a higher
+color mode and edit the image.
+
+  For programs that don't show Bitmap Fonts in the Font Selector, you
+may be able to get the font to work by typing in:
+homespun brk
+
+  When using the TTF version, try using it with anti-aliasing off.
+
+
+If you have any questions or comments, you can e-mail me at
[email protected]
+
+You can visit my Webpage <ÆNIGMA GAMES & FONTS> at
+http://www.aenigmafonts.com/
+
+________________
+INSTALLING FONTS
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+  There's a couple of ways to install Fonts. The 'easy' way to
+install fonts is to just Unzip/place the font file [.ttf] into your
+Windows\Fonts directory (I always use this method). If you're unable
+to do it the 'easy' way, then try to do it this way (for Windows
+95/98/NT):
+
+1] Unzip the Font(s) to a folder (or somewhere, just remember where
+you unzipped it) on your Computer.
+
+2] Next, click on the START button, then select SETTINGS then
+CONTROL PANEL.
+
+3] When the Control Panel Window pops up, Double Click on FONTS.
+
+4] When the FONTS window pops up, select File then Install New Font...
+
+5] A Add Fonts window will pop up, just go to the folder that you
+unzipped the Font(s) to, select the Font(s) and then click on OK.
+Now the Font(s) are installed.
+
+  Now you can use the Font(s) in programs that utilize Fonts.  Make
+sure that you install the font(s) first, then open up your apps
+(so the app will recognize the font).    Sometimes you'll have to
+wait until your computer 'auto-refreshes' for programs to recognize
+fonts (Windows is sometimes slow to do that).  You can refresh your
+computer quicker by going into Windows Explorer -or- My Computer and
+press F5 (or in the menubar select VIEW then REFRESH).
+
+
+__________
+DISCLAIMER
+¯¯¯¯¯¯¯¯¯¯
+-The font(s) in this zip file were created by me (Brian Kent).  All
+of my Fonts are Freeware, you can use them any way you want to
+(Personal use, Commercial use, or whatever).
+
+-If you have a Font related site and would like to offer my fonts on
+your site, go right ahead. All I ask is that you keep this text file
+intact with the Font.
+
+-You may not Sell or Distribute my Fonts for profit or alter them in
+any way without asking me first.  [e-mail -  [email protected]]

二进制
gui.mod/raygui/styles/bluish/homespun.ttf


二进制
gui.mod/raygui/styles/bluish/screenshot.png


二进制
gui.mod/raygui/styles/bluish/style_table.png


+ 16 - 0
gui.mod/raygui/styles/candy/README.md

@@ -0,0 +1,16 @@
+style: candy
+-------------
+Sweet, colorful, tasty! Enjoy this funfair ride and be careful with the witch of the candy house!
+
+![candy style table](style_table.png)
+
+screenshot
+-----------
+
+![candy style screen](screenshot.png)
+
+about font
+-----------
+"V5 Eastergothic" font by vFive Digital (Roberto Christen).
+
+100% free font, downloaded from dafont.com: [v5eastergothic](https://www.dafont.com/v5eastergothic.font)

+ 24 - 0
gui.mod/raygui/styles/candy/candy.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 15 0 v5easter.ttf
+p 00 00 0xe58b68ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0xfeda96ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0xe59b5fff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0xee813fff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0xfcd85bff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0xfc6955ff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0xb34848ff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0xeb7272ff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0xbd4a4aff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0x94795dff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0xc2a37aff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x9c8369ff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x0000000f    TEXT_SIZE
+p 00 17 0x00000001    TEXT_SPACING
+p 00 18 0xd77575ff    DEFAULT_LINE_COLOR
+p 00 19 0xfff5e1ff    DEFAULT_BACKGROUND_COLOR

+ 27 - 0
gui.mod/raygui/styles/candy/font_readme.txt

@@ -0,0 +1,27 @@
+
+V5 Easter Gothic
+----------------
+Instructions:
+
+
+++ Easter Gothic ++
+
+For screen use, set at 15pt or any multiple
+of 15 (display).  Turn antialiasing off.  Set 
+tracking to 100 for best results.
+
+---------------
+Usage:  This is a free font--you may use 
+this and other V5 fonts at will.  It may not 
+be sold, altered, or improperly credited,
+however.  All I ask is that you kindly inform 
+me if you find this font useful, and where
+you've used it.
+
+Enjoy,
+
+©2000 
+Roberto Christen
[email protected]
+
+

二进制
gui.mod/raygui/styles/candy/screenshot.png


二进制
gui.mod/raygui/styles/candy/style_table.png


二进制
gui.mod/raygui/styles/candy/v5easter.ttf


+ 16 - 0
gui.mod/raygui/styles/cherry/README.md

@@ -0,0 +1,16 @@
+style: cherry
+--------------
+Sweet with a touch of liquour, covered in chocolate, just give it a try! Not suitable for every palate, only the most demanding. 
+
+![cherry style table](style_table.png)
+
+screenshot
+-----------
+
+![cherry style screen](screenshot.png)
+
+about font
+-----------
+"Westington" font by Hazel Abbiati.
+
+100% free font, downloaded from dafont.com: [westington](https://www.dafont.com/westington.font)

二进制
gui.mod/raygui/styles/cherry/Westington.ttf


+ 24 - 0
gui.mod/raygui/styles/cherry/cherry.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 15 0 Westington.ttf
+p 00 00 0xda5757ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0x753233ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0xe17373ff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0xfaaa97ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0xe06262ff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0xfdb4aaff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0xe03c46ff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0x5b1e20ff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0xc2474fff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0xa19292ff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0x706060ff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x9e8585ff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x0000000f    TEXT_SIZE
+p 00 17 0x00000000    TEXT_SPACING
+p 00 18 0xfb8170ff    DEFAULT_LINE_COLOR
+p 00 19 0x3a1720ff    DEFAULT_BACKGROUND_COLOR

二进制
gui.mod/raygui/styles/cherry/screenshot.png


二进制
gui.mod/raygui/styles/cherry/style_table.png


二进制
gui.mod/raygui/styles/cyber/Kyrou 7 Wide.ttf


+ 16 - 0
gui.mod/raygui/styles/cyber/README.md

@@ -0,0 +1,16 @@
+style: cyber
+-------------
+Future is now! Neons and shadows, city never sleeps! Robots waiting in the corners and expensive vending machines! You got the style!
+
+![cyber style table](style_table.png)
+
+screenshot
+-----------
+
+![cyber style screen](screenshot.png)
+
+about font
+-----------
+"Grixel Kyrou 7 Wide" font by [Nikos Giannakopoulos](http://www.grixel.gr/).
+
+100% free font, downloaded from dafont.com: [grixel-kyrou-7-wide](https://www.dafont.com/grixel-kyrou-7-wide.font)

+ 24 - 0
gui.mod/raygui/styles/cyber/cyber.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 14 0 Kyrou 7 Wide.ttf
+p 00 00 0x2f7486ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0x024658ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0x51bfd3ff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0x82cde0ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0x3299b4ff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0xb6e1eaff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0xeb7630ff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0xffbc51ff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0xd86f36ff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0x134b5aff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0x02313dff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x17505fff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x0000000e    DEFAULT_TEXT_SIZE
+p 00 17 0x00000000    DEFAULT_TEXT_SPACING
+p 00 18 0x81c0d0ff    DEFAULT_LINE_COLOR
+p 00 19 0x00222bff    DEFAULT_BACKGROUND_COLOR

+ 36 - 0
gui.mod/raygui/styles/cyber/font_readme.txt

@@ -0,0 +1,36 @@
+Thank you for downloading the free Grixel fonts. You can use them in your personal and commercial projects too. They include Western European, Central European, Turkish and Greek characters. They are Unicode TrueType fonts and are optimized to work in both Windows XP and Mac OS X platforms using Adobe Photoshop CS2 and Macromedia Flash 8.
+
+
+Grixel fonts are under Creative Commons Attribution-NoDerivs 2.5 License which can be found here:
+
+http://creativecommons.org/licenses/by-nd/2.5/
+
+===============================================================
+Attribution-NoDerivs 2.5
+
+You are free:
+
+    * to copy, distribute, display, and perform the work
+    * to make commercial use of the work
+
+Under the following conditions:
+
+by 	
+Attribution. You must attribute the work in the manner specified by the author or licensor.
+
+nd 	
+No Derivative Works. You may not alter, transform, or build upon this work.
+
+    * For any reuse or distribution, you must make clear to others the license terms of this work.
+    * Any of these conditions can be waived if you get permission from the copyright holder.
+
+Your fair use and other rights are in no way affected by the above.
+===============================================================
+
+
+In no event shall Nikos Giannakopoulos be held liable to you for any consequential or incidental damages, including any lost revenue, profits, goodwill or savings, or for any claim by any third party caused by using these fonts.
+
+Please read the UsageGuides.pdf before you use them.
+
+
+Grixel - Greek pixel fonts | Nikos Giannakopoulos | www.grixel.gr

二进制
gui.mod/raygui/styles/cyber/screenshot.png


二进制
gui.mod/raygui/styles/cyber/style_table.png


+ 14 - 0
gui.mod/raygui/styles/default/README.md

@@ -0,0 +1,14 @@
+style: default
+---------------
+raylib style, simple and easy-to-use. Light colors, wide borders, a sophisticated touch.
+
+![default style table](style_table.png)
+
+screenshot
+-----------
+
+![default style screen](screenshot.png)
+
+about font
+-----------
+raylib font by Ramon Santamaria ([@raysan5](https://twitter.com/raysan5)).

+ 69 - 0
gui.mod/raygui/styles/default/default.rgs

@@ -0,0 +1,69 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+p 00 00 0x838383ff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0xc9c9c9ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0x686868ff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0x5bb2d9ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0xc9effeff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0x6c9bbcff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0x0492c7ff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0x97e8ffff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0x368bafff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0xb5c1c2ff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0xe6e9e9ff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0xaeb7b8ff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 12 0x1           DEFAULT_BORDER_WIDTH
+p 00 13 0x0           DEFAULT_TEXT_PADDING
+p 00 14 0x1           DEFAULT_TEXT_ALIGNMENT
+p 00 15 0x0           DEFAULT_RESERVED
+p 00 16 0xa           DEFAULT_TEXT_SIZE
+p 00 17 0x1           DEFAULT_TEXT_SPACING
+p 00 18 0x90abb5ff    DEFAULT_LINE_COLOR
+p 00 19 0xf5f5f5ff    DEFAULT_BACKGROUND_COLOR
+p 01 14 0x0           LABEL_TEXT_ALIGNMENT
+p 02 12 0x2           BUTTON_BORDER_WIDTH
+p 03 16 0x2           TOGGLE_GROUP_PADDING
+p 04 16 0xf           SLIDER_SLIDER_WIDTH
+p 04 13 0x5           SLIDER_TEXT_PADDING
+p 05 16 0x1           PROGRESSBAR_PROGRESS_PADDING
+p 06 13 0x5           CHECKBOX_TEXT_PADDING
+p 06 14 0x2           CHECKBOX_TEXT_ALIGNMENT
+p 06 16 0x1           CHECKBOX_CHECK_PADDING
+p 07 16 0x1e          COMBOBOX_COMBO_BUTTON_WIDTH
+p 07 17 0x2           COMBOBOX_COMBO_BUTTON_PADDING
+p 08 16 0x10          DROPDOWNBOX_ARROW_PADDING
+p 08 17 0x2           DROPDOWNBOX_DROPDOWN_ITEMS_PADDING
+p 09 13 0x5           TEXTBOX_TEXT_PADDING
+p 09 14 0x0           TEXTBOX_TEXT_ALIGNMENT
+p 09 16 0x5           TEXTBOX_TEXT_LINES_PADDING
+p 09 17 0xf0fffeff    TEXTBOX_COLOR_SELECTED_FG
+p 09 18 0x839affe0    TEXTBOX_COLOR_SELECTED_BG
+p 10 13 0x4           VALUEBOX_TEXT_PADDING
+p 10 14 0x0           VALUEBOX_TEXT_ALIGNMENT
+p 11 13 0x4           SPINNER_TEXT_PADDING
+p 11 14 0x0           SPINNER_TEXT_ALIGNMENT
+p 11 16 0x14          SPINNER_SPIN_BUTTON_WIDTH
+p 11 17 0x2           SPINNER_SPIN_BUTTON_PADDING
+p 12 16 0x1e          LISTVIEW_LIST_ITEMS_HEIGHT
+p 12 17 0x2           LISTVIEW_LIST_ITEMS_PADDING
+p 12 18 0xa           LISTVIEW_SCROLLBAR_WIDTH
+p 12 19 0x2           LISTVIEW_SCROLLBAR_SIDE
+p 13 16 0x6           COLORPICKER_COLOR_SELECTOR_SIZE
+p 13 17 0x14          COLORPICKER_HUEBAR_WIDTH
+p 13 18 0xa           COLORPICKER_HUEBAR_PADDING
+p 13 19 0x6           COLORPICKER_HUEBAR_SELECTOR_HEIGHT
+p 13 20 0x2           COLORPICKER_HUEBAR_SELECTOR_OVERFLOW
+p 14 12 0x0           SCROLLBAR_BORDER_WIDTH
+p 14 16 0x6           SCROLLBAR_ARROWS_SIZE
+p 14 17 0x0           SCROLLBAR_ARROWS_VISIBLE
+p 14 18 0x0           SCROLLBAR_SCROLL_SLIDER_PADDING
+p 14 19 0x10          SCROLLBAR_SCROLL_SLIDER_SIZE
+p 14 20 0x0           SCROLLBAR_SCROLL_PADDING
+p 14 21 0xa           SCROLLBAR_SCROLL_SPEED
+p 15 13 0xa           STATUSBAR_TEXT_PADDING
+p 15 14 0x0           STATUSBAR_TEXT_ALIGNMENT

二进制
gui.mod/raygui/styles/default/screenshot.png


二进制
gui.mod/raygui/styles/default/style_table.png


二进制
gui.mod/raygui/styles/jungle/Pixel Intv.otf


+ 16 - 0
gui.mod/raygui/styles/jungle/README.md

@@ -0,0 +1,16 @@
+style: jungle
+--------------
+Sunset in the jungle, trees do not let to see the last rays of sun on the horizon, small creek in the path, mug on the shoes, a touch of danger and the adventure feeling, get into your jeep and drive with this style.  
+
+![jungle style table](style_table.png)
+
+screenshot
+-----------
+
+![jungle style screen](screenshot.png)
+
+about font
+-----------
+"Pixel Intv" font by [Pixel Sagas](http://www.pixelsagas.com) (Neale and Shayna Davidson).
+
+100% free font, downloaded from dafont.com: [pixel-intv](https://www.dafont.com/pixel-intv.font)

+ 47 - 0
gui.mod/raygui/styles/jungle/font_readme.txt

@@ -0,0 +1,47 @@
+Shareware/ Font License
+
+Pixel Sagas Freeware Fonts EULA (End User License Agreement) and Software Inclusion Agreement
+
+"Purchaser" and "User" may be used interchangeably in this agreement.
+
+"Pixel Sagas" and "Neale Davidson" may be used interchangeably in this agreement. These all refer to the intellectual and legal property of Neale Davidson.
+
+Usage
+
+Pixel Saga's Shareware Fonts are free to use for personal, non-commercial purposes. No payment is necessary to use Pixel Saga's Freeware Fonts for personal use, and there is no limit to the amount of prints, pages, or other medium to be produced using them. However, you cannot offer the font for commercial sale, or offer for direct download. The inclusion othe font name and/or site URL in the credits or documentation when it is used is appreciated, but this is not mandatory.
+
+Payment
+
+Payment is not required for the use of Pixel Saga's Shareware Fonts. Commercial use requires a modest fee which can be paid through the pixelsagas.com web site through Paypal.com's services. The transaction receipt for any shareware "commercial license" purchase will suffice as proof of license.
+
+Support
+
+Font installation help is available at http://www.pixelsagas.com. If you experience problems with any Pixel Saga's Freeware font (such as spacing issues or missing characters), please verify that you have the correct and current version of the fonts. In the case of Freeware fonts, downloading the font directly from the Pixel Sagas site will ensure that the font files have not been altered.
+
+Software Inclusion Agreement
+
+Pixel Saga's software products are protected by copyright laws and International copyright treaties, as well as other intellectual property laws and treaties. All Pixel Saga's software products are licensed, not sold.
+
+1) GRANT OF LICENSE
+
+This document grants the user the following rights:
+
+Installation and Use. The user may install and use an unlimited number of copies of the software product. The user may not offer Pixel Sagas freeware fonts for direct download unless the user has received explicit, written permission from Neale Davidson. Otherwise please direct users to the http://www.pixelsagas.com website. Pixel Sagas freeware fonts may, however, be embedded for web, publication, or general software use.
+
+2) WARRANTIES
+
+None
+
+Pixel Sagas expressly disclaims any warranty for the software product. The software product and any related documentation is provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties or merchantability, fitness for a particular purpose, or non-infringement. The entire risk arising out of use or performance of the software product remains with the user.
+
+No Liability For Consequential Damages.
+
+In no event shall Neale Davidson or Pixel Sagas be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use this product, even if Pixel Sagas has been advised of the possibility of such damages.
+
+3) MISCELLANEOUS
+
+Should the user have any questions concerning this document or you desire to contact Neale Davidson for any reason, please email [email protected] .
+
+Governing Law
+
+This agreement is governed by and subject to the laws of the United States of America.

+ 24 - 0
gui.mod/raygui/styles/jungle/jungle.rgs

@@ -0,0 +1,24 @@
+#
+# rgs style text file (v3.1) - raygui style file generated using rGuiStyler
+#
+# Style properties:
+#   f <gen_font_size> <charmap_file> <font_file>
+#   p <control_id> <property_id> <property_value> <property_name>
+#
+f 12 0 Pixel Intv.otf
+p 00 00 0x60827dff    DEFAULT_BORDER_COLOR_NORMAL
+p 00 01 0x2c3334ff    DEFAULT_BASE_COLOR_NORMAL
+p 00 02 0x82a29fff    DEFAULT_TEXT_COLOR_NORMAL
+p 00 03 0x5f9aa8ff    DEFAULT_BORDER_COLOR_FOCUSED
+p 00 04 0x334e57ff    DEFAULT_BASE_COLOR_FOCUSED
+p 00 05 0x6aa9b8ff    DEFAULT_TEXT_COLOR_FOCUSED
+p 00 06 0xa9cb8dff    DEFAULT_BORDER_COLOR_PRESSED
+p 00 07 0x3b6357ff    DEFAULT_BASE_COLOR_PRESSED
+p 00 08 0x97af81ff    DEFAULT_TEXT_COLOR_PRESSED
+p 00 09 0x5b6462ff    DEFAULT_BORDER_COLOR_DISABLED
+p 00 10 0x2c3334ff    DEFAULT_BASE_COLOR_DISABLED
+p 00 11 0x666b69ff    DEFAULT_TEXT_COLOR_DISABLED
+p 00 16 0x0000000c    TEXT_SIZE
+p 00 17 0x00000000    TEXT_SPACING
+p 00 18 0x638465ff    DEFAULT_LINE_COLOR
+p 00 19 0x2b3a3aff    DEFAULT_BACKGROUND_COLOR

二进制
gui.mod/raygui/styles/jungle/screenshot.png


部分文件因为文件数量过多而无法显示