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