72 Commits
2.6 ... 2.8

Author SHA1 Message Date
7dae5b06f7 use the same style of dll export/import definition and extern c as raylib, so it actually works on windows. (#115) 2020-12-26 19:27:50 +01:00
Ray
f5bd6c08f8 Update gui_file_dialog.h 2020-12-18 20:06:38 +01:00
Ray
3b44da667b Updated to raylib 3.5
Use GetCharPressed() instead of GetKeyPressed()
2020-12-18 19:50:57 +01:00
60605f01b6 Handle CRLF line endings reading fontFileName. (#114)
If you have a style file with CRLF line endings and specify a font file on a system that expects LF line endings, then the font file will fail to load with an error such as...

WARNING: FILEIO: [./assets/terminal/Mecha.ttf
] Failed to open file

...because it sees the CR as part of the name.

Adding '\r' to the negated scanset for sscanf() fixes the issue.
2020-12-14 16:11:17 +01:00
a380ef80c1 Missing closing parentheses for if statement (#113)
Added a missing parenthesis to the if statement for the *iconId* example.
2020-12-12 09:59:07 +01:00
7eda4008e2 Add missing examples in Makefile (#111)
Co-authored-by: epsimatt <epsimatt@protonmail.com>
2020-11-20 23:16:06 +01:00
Ray
b73eb56f3c Update image_exporter.c 2020-10-05 20:08:47 +02:00
07b30c30af Fix tiny spelling mistake (#103) 2020-07-21 19:28:19 +02:00
95b225b90c GuiTextBox(): Support Unicode inputs #99 2020-07-13 19:53:17 +02:00
6d2d6819fa GuiTextBoxMulti now will also break lines when encountering a newline character (#97)
* Fix for issue #94: infinite loop on space-free sequences in text that are wider than textbox bounds

marked no lastSpacePos as -1.
check for a space-char had to come earlier than check for width overrun.
if no space found in this line but line too wide, wrap sequence and start new line with textWidth of last character.
reset lastSpacePos on every new line.

* GuiTextBoxMulti now will also break when encountering a newline character

Co-authored-by: Ray <raysan5@gmail.com>
2020-07-04 11:30:33 +02:00
4eda62925c Fix for issue #94: infinite loop on space-free sequences in text that are wider than textbox bounds (#95)
marked no lastSpacePos as -1.
check for a space-char had to come earlier than check for width overrun.
if no space found in this line but line too wide, wrap sequence and start new line with textWidth of last character.
reset lastSpacePos on every new line.
2020-06-20 17:51:46 +02:00
3e61557f25 Clean up CMake files (#90) 2020-05-18 19:32:22 +02:00
65bad19e26 Update raygui.h 2020-05-18 18:31:45 +02:00
4643d3769d Corrected issue with GuiCOlorPicker() drifting 2020-05-05 10:28:01 +02:00
8c33be58b2 Update raygui Rectangle to match raylib Rectangle (#88)
Rectangle in raygui should use a float.
2020-05-04 20:14:04 +02:00
8a38a8028e Bumped version 2020-05-03 21:25:00 +02:00
76d734bb30 Move all rectangles drawing to one single function
Now all controls just use GuiDrawRectangle() that receives border parameters if required, it replaces previous DrawRectangle()/DrawRectangleRec() + DrawRectangleLinesEx() combinations.

It centralizes rectangles drawing into a single function, allowing some further customization in the future if required...
2020-05-03 21:23:45 +02:00
4758b45676 Corrected some typos 2020-05-03 21:19:53 +02:00
fa8b958a91 Move CMake files to projects/CMake (#87)
Fixes #86
2020-05-01 13:31:15 +02:00
feb1a6c874 fixed package mode in FindRaylib (#85) 2020-04-29 12:40:24 +02:00
e689c710e4 Update CMakeLists.txt (#83)
Remove comma after RAYGUI_HEADERS or make install will not install the headers because RAYGUI_HEADERS is not set. ", " is an unreported syntactic error.
2020-04-24 23:16:18 +02:00
0fdacc87f6 Add CMake definitions (#79) 2020-04-16 13:24:03 +02:00
5191022a6b Fix unknown stack array size (#80)
Compiler expected a static value. Writing 64 directly in the declaration should fix it up.
2020-04-16 13:22:28 +02:00
3e1d420e60 Review examples copyright 2020-04-07 23:04:39 +02:00
7f4794c31d Review gui_file_dialog with proposed improvements
Proposed improvements in: https://github.com/raysan5/raylib/issues/1101
2020-04-06 23:20:38 +02:00
6346ae2246 Remove trailing spaces 2020-04-06 23:19:42 +02:00
b2974f3d28 Review issue sscanf() and hex value #78 2020-03-26 18:04:10 +01:00
Ray
18a32e61ab GuiGrid() Corrected issue with div by 0 2020-03-12 12:29:20 +01:00
Ray
6cf73a3054 GuiTextBoxMulti(), minor tweak to align cursor 2020-03-11 16:09:58 +01:00
Ray
9d911f7104 REVIEWED: IsMouseButtonPressed() to use define value 2020-03-11 16:00:41 +01:00
Ray
d3c810311c REVIEWED: GuiTextBoxMulti() #54
Simplified code, avoid line breaking.

WARNING: If a line is longer than box width, it crashes... word-wrap implementation requires some review...
2020-03-11 16:00:09 +01:00
d878d38e40 Added new example for a property list control (#76) 2020-03-11 12:32:56 +01:00
Ray
9d1e48bfe6 Expose internal GuiColor*() controls #74 2020-03-11 12:27:20 +01:00
Ray
24de442135 Update LICENSE link 2020-02-28 10:19:21 +01:00
Ray
6f80bfbbd1 Updated to raygui 2.7 2020-02-20 16:43:24 +01:00
Ray
ffdeef8d17 Experimenting with a tooltips API
Found several limitations:
 - Tooltip timming can not be properly set on imgui mode
 - Tooltip underlap to controls drawn after current control

Still, a quite interesting feature for further analysis.
2020-02-20 16:36:18 +01:00
Ray
b8932dab26 RENAMED: riconsdata.h to ricons.h 2020-02-14 23:18:43 +01:00
Ray
d297b5d7d9 GuiTextEditor() control example -WIP- 2020-02-10 23:57:51 +01:00
Ray
1f088bf174 Update README.md 2020-02-10 16:58:44 +01:00
fd349ca95c Fix parameters and guess at constants (#70) 2020-02-08 01:13:04 +01:00
Ray
8d5f8f28a4 Review LIST_ITEMS_HEIGHT property 2020-02-07 11:40:59 +01:00
Ray
efe2a42cee Remove unneded define 2020-01-30 18:02:26 +01:00
Ray
4fb2b73a15 Addressed issue #66
NOTE: GetDirectoryPath() has also been updated in raylib, latest master branch version must be used!
2020-01-26 12:55:14 +01:00
Ray
aa28f6c759 Review GetTextIcon() for #67 2020-01-26 12:00:33 +01:00
Ray
e1e296583e Review custom allocators warnings 2020-01-26 12:00:14 +01:00
Ray
962661b7ea Ignore Visual Studio generated files 2020-01-26 11:59:55 +01:00
Ray
4047b43b10 Removed atoi() dependency 2020-01-24 18:01:57 +01:00
Ray
146068751c Improved standalone support and example 2020-01-22 13:43:46 +01:00
fce438cd1c Support custom memory allocators 2020-01-19 11:21:29 +01:00
09d583687a Review functions declaration properties 2020-01-19 11:09:09 +01:00
9f589be0c2 🐛 Fixed GuiGrid, GuiTextBoxMult, README (outdated #define for icons) (#64) 2020-01-12 23:59:41 +01:00
40ceed83cc Update year to 2020 2020-01-06 13:50:05 +01:00
Ray
0843425e4e Rename and review riconsdata.h 2019-11-26 00:54:39 +01:00
Ray
f296f53a1c Review defines 2019-11-26 00:54:13 +01:00
Ray
1beef1c0e0 Move ricons logic to raygui
Now ricons.h only contains icons data, so, it can be easily generated (and replaced) using rGuiIcons tool.
2019-11-25 19:54:32 +01:00
Ray
9fd0f91dea Rename and review textbox_extended_demo 2019-11-25 19:41:40 +01:00
Ray
1cc900bff9 Review some logic 2019-11-25 19:41:15 +01:00
Ray
a2c5ffc272 Move text box extended to separate module 2019-11-25 19:07:40 +01:00
58307af091 Fixed GuiSpinner defines (#60)
GuiSpinner and ValueBox were being disabled when the  RAYGUI_TEXTBOX_EXTENDED was set.
2019-11-04 10:44:34 +01:00
Ray
72eac06c29 Added VS2017 project 2019-10-21 18:00:12 +02:00
Ray
416df0ad4e Reduce Jungle style text spacing 2019-10-21 17:59:47 +02:00
Ray
b312ba5f78 Remove trailing spaces 2019-10-17 17:16:47 +02:00
Ray
48c355315b Review text spacing for styles 2019-09-30 20:34:17 +02:00
Ray
e9833c1a4f Add enum names and one new icon 2019-09-30 17:51:55 +02:00
Ray
2c96d4a157 Improved module for rGuiIcons
- ADDED: GuiLoadIcons()
 - ADDED: GuiGetIconData() and GuiSetIconData()
 - ADDED: GuiSetIconPixel(), GuiClearIconPixel(), GuiCheckIconPixel()
2019-09-30 17:36:34 +02:00
Ray
f164f744ac Review some defines naming and exposure 2019-09-30 17:34:30 +02:00
Ray
00fb56245d Update raygui.h 2019-09-17 00:32:27 +02:00
Ray
6469c92b69 DEFAULT properties propagation is done automatically 2019-09-16 00:34:49 +02:00
d3b2f49da3 Update GuiListViewEx()
Security check in case of NULL items text provided
2019-09-15 17:53:59 +02:00
5572d37fe0 REMOVED: GuiLoadStyleProps() and GuiUpdateStyleComplete()
Those functions were useless and confusing, design simplified!

Now GuiSetStyle() propagates default property values automatically
2019-09-15 17:53:19 +02:00
b888ce73ef Update version to avoid confusions
Current raygui 2.6 is already published, so, I'm working on raygui 2.7
2019-09-14 19:02:35 +02:00
Ray
ffb1d9f9a8 Review style: cyber
Make normal text slightly brighter
2019-09-13 16:38:08 +02:00
31 changed files with 5032 additions and 2458 deletions

28
.gitignore vendored
View File

@ -34,3 +34,31 @@
# VSCode files # VSCode files
.vscode/ .vscode/
# Ignore files build by Visual Studio
[Dd]ebug
[Rr]elease
*.vs
*.obj
*.pdb
*.aps
*.user
# *.vcproj
# *.vcxproj*
# *.sln
*.vspscc
*_i.c
*.i
*.icf
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
build

View File

@ -1,6 +1,6 @@
zlib License zlib License
Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
This software is provided "as-is", without any express or implied warranty. In no event This software is provided "as-is", without any express or implied warranty. In no event
will the authors be held liable for any damages arising from the use of this software. will the authors be held liable for any damages arising from the use of this software.

View File

@ -4,9 +4,9 @@
raygui was initially inspired by [Unity IMGUI](https://docs.unity3d.com/Manual/GUIScriptingGuide.html) (immediate mode GUI API). raygui was initially inspired by [Unity IMGUI](https://docs.unity3d.com/Manual/GUIScriptingGuide.html) (immediate mode GUI API).
raygui was originated as an auxiliar module for [raylib](https://github.com/raysan5/raylib) to create simple GUI interfaces using raylib graphic style (simple colors, plain rectangular shapes, wide borders, raylib default font...). raygui was originated as an auxiliar module for [raylib](https://github.com/raysan5/raylib) to create simple GUI interfaces using raylib graphic style (simple colors, plain rectangular shapes, wide borders...).
raygui is intended for **tools development**; it has already been used to develop the following tools: [rFXGen](https://github.com/raysan5/rfxgen), [rTexViewer](https://raylibtech.itch.io/rtexviewer), [rGuiStyler](https://raylibtech.itch.io/rguistyler) and [rGuiLayout](https://raylibtech.itch.io/rguilayout). raygui is intended for **tools development**; it has already been used to develop the following tools: [rFXGen](https://github.com/raysan5/rfxgen), [rTexViewer](https://raylibtech.itch.io/rtexviewer), [rTexPacker](https://raylibtech.itch.io/rtexpacker) [rGuiStyler](https://raylibtech.itch.io/rguistyler), [rGuiLayout](https://raylibtech.itch.io/rguilayout) and [rGuiIcons](https://raylibtech.itch.io/rguiicons)
<br> <br>
@ -45,20 +45,22 @@ Styles can be loaded at runtime using raygui `GuiLoadStyle()` function. Simple a
*rGuiStyler v3.1 - raygui styles editor, useful to create custom styles* *rGuiStyler v3.1 - raygui styles editor, useful to create custom styles*
## raygui icons: ricons ## raygui icons
`raygui` includes a separate module with a set of custom handcrafter icons, ready to be used and integrated in a easy way with `raygui`. This module is called `ricons.h` and can be automatically included just defining `RAYGUI_SUPPORT_RICONS` before including `raygui`. `raygui` supports custom icons provided as an external array of data. To support icons just define `RAYGUI_SUPPORT_ICONS` before including `raygui`.
A set of custom handcrafted icons is provided in [`riconsdata`](src/riconsdata.h). This set of icons can be created and customized using [rGuiIcons](https://raylibtech.itch.io/rguiicons) tool.
<img align="right" src="images/raygui_ricons.png"> <img align="right" src="images/raygui_ricons.png">
```c ```c
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#define RAYGUI_SUPPORT_RICONS #define RAYGUI_SUPPORT_ICONS
#include "raygui.h" #include "raygui.h"
``` ```
To use any of those icons in your gui, just preprend *iconId* to any text written within `raygui` controls: To use any of those icons in your gui, just preprend *iconId* to any text written within `raygui` controls:
```c ```c
if (GuiButton(rec, "#05#Open Image") { /* ACTION */ } if (GuiButton(rec, "#05#Open Image")) { /* ACTION */ }
``` ```
or use the provided `GuiIconText()` function to prepend it automatically, using a clearer identifier. or use the provided `GuiIconText()` function to prepend it automatically, using a clearer identifier.
```c ```c
@ -68,4 +70,4 @@ if (GuiButton(rec, GuiIconText(RICON_FILE_OPEN, "Open Image"))) { /* ACTION */ }
license license
------- -------
raygui is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. Check [LICENSE](LICENSE.md) for further details. raygui is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. Check [LICENSE](LICENSE) for further details.

View File

@ -352,7 +352,8 @@ EXAMPLES = \
image_raw_importer/image_raw_importer \ image_raw_importer/image_raw_importer \
portable_window/portable_window \ portable_window/portable_window \
scroll_panel/gui_scroll_panel \ scroll_panel/gui_scroll_panel \
text_box_selection/gui_text_box text_box_selection/textbox_extended_demo \
text_editor/text_editor
CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST)) CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
@ -385,4 +386,4 @@ endif
ifeq ($(PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js del *.o *.html *.js
endif endif
@echo Cleaning done @echo Cleaning done

View File

@ -30,14 +30,14 @@
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech) * Copyright (c) 2020 Ramon Santamaria (@raysan5)
* *
**********************************************************************************************/ **********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#define RAYGUI_SUPPORT_RICONS #define RAYGUI_SUPPORT_ICONS
#include "../../src/raygui.h" #include "../../src/raygui.h"
#undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again #undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
@ -80,7 +80,7 @@ int main()
int listViewExFocus = -1; int listViewExFocus = -1;
const char *listViewExList[8] = { "This", "is", "a", "list view", "with", "disable", "elements", "amazing!" }; const char *listViewExList[8] = { "This", "is", "a", "list view", "with", "disable", "elements", "amazing!" };
char multiTextBoxText[141] = "Multi text box"; char multiTextBoxText[256] = "Multi text box";
bool multiTextBoxEditMode = false; bool multiTextBoxEditMode = false;
Color colorPickerValue = RED; Color colorPickerValue = RED;
@ -160,7 +160,9 @@ int main()
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
GuiSetTooltip("Save current file.");
if (GuiButton((Rectangle){ 25, 255, 125, 30 }, GuiIconText(RICON_FILE_SAVE, "Save File"))) showTextInputBox = true; if (GuiButton((Rectangle){ 25, 255, 125, 30 }, GuiIconText(RICON_FILE_SAVE, "Save File"))) showTextInputBox = true;
GuiClearTooltip();
GuiGroupBox((Rectangle){ 25, 310, 125, 150 }, "STATES"); GuiGroupBox((Rectangle){ 25, 310, 125, 150 }, "STATES");
GuiLock(); GuiLock();
@ -187,7 +189,7 @@ int main()
toggleGroupActive = GuiToggleGroup((Rectangle){ 165, 400, 140, 25 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", toggleGroupActive); toggleGroupActive = GuiToggleGroup((Rectangle){ 165, 400, 140, 25 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", toggleGroupActive);
// Third GUI column // Third GUI column
if (GuiTextBoxMulti((Rectangle){ 320, 25, 225, 140 }, multiTextBoxText, 141, multiTextBoxEditMode)) multiTextBoxEditMode = !multiTextBoxEditMode; if (GuiTextBoxMulti((Rectangle){ 320, 25, 225, 140 }, multiTextBoxText, 256, multiTextBoxEditMode)) multiTextBoxEditMode = !multiTextBoxEditMode;
colorPickerValue = GuiColorPicker((Rectangle){ 320, 185, 196, 192 }, colorPickerValue); colorPickerValue = GuiColorPicker((Rectangle){ 320, 185, 196, 192 }, colorPickerValue);
sliderValue = GuiSlider((Rectangle){ 355, 400, 165, 20 }, "TEST", TextFormat("%2.2f", (float)sliderValue), sliderValue, -50, 100); sliderValue = GuiSlider((Rectangle){ 355, 400, 165, 20 }, "TEST", TextFormat("%2.2f", (float)sliderValue), sliderValue, -50, 100);

View File

@ -11,14 +11,14 @@
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech) * Copyright (c) 2020 Ramon Santamaria (@raysan5)
* *
**********************************************************************************************/ **********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#define RAYGUI_SUPPORT_RICONS #define RAYGUI_SUPPORT_ICONS
#include "../../src/raygui.h" #include "../../src/raygui.h"
#undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again #undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
@ -35,17 +35,17 @@ int main()
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------
int screenWidth = 800; int screenWidth = 800;
int screenHeight = 560; int screenHeight = 560;
InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog"); InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
SetExitKey(0); SetExitKey(0);
// Custom file dialog // Custom file dialog
GuiFileDialogState fileDialogState = InitGuiFileDialog(); GuiFileDialogState fileDialogState = InitGuiFileDialog(420, 310, GetWorkingDirectory(), false);
bool exitWindow = false; bool exitWindow = false;
char fileNameToLoad[512] = { 0 }; char fileNameToLoad[512] = { 0 };
Texture texture = { 0 }; Texture texture = { 0 };
SetTargetFPS(60); SetTargetFPS(60);
@ -57,7 +57,7 @@ int main()
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
exitWindow = WindowShouldClose(); exitWindow = WindowShouldClose();
if (fileDialogState.SelectFilePressed) if (fileDialogState.SelectFilePressed)
{ {
// Load image file (if supported extension) // Load image file (if supported extension)
@ -67,7 +67,7 @@ int main()
UnloadTexture(texture); UnloadTexture(texture);
texture = LoadTexture(fileNameToLoad); texture = LoadTexture(fileNameToLoad);
} }
fileDialogState.SelectFilePressed = false; fileDialogState.SelectFilePressed = false;
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -77,20 +77,20 @@ int main()
BeginDrawing(); BeginDrawing();
ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE); DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE);
DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK); DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK);
DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY); DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
// raygui: controls drawing // raygui: controls drawing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (fileDialogState.fileDialogActive) GuiLock(); if (fileDialogState.fileDialogActive) GuiLock();
if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true; if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true;
GuiUnlock(); GuiUnlock();
// GUI: Dialog Window // GUI: Dialog Window
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
GuiFileDialog(&fileDialogState); GuiFileDialog(&fileDialogState);

View File

@ -1,6 +1,6 @@
/******************************************************************************************* /*******************************************************************************************
* *
* FileDialog v1.0.0 - Modal file dialog to open/save files * FileDialog v1.1 - Modal file dialog to open/save files
* *
* MODULE USAGE: * MODULE USAGE:
* #define GUI_FILE_DIALOG_IMPLEMENTATION * #define GUI_FILE_DIALOG_IMPLEMENTATION
@ -16,13 +16,24 @@
* - DirectoryExists() * - DirectoryExists()
* - FileExists() * - FileExists()
* *
* LICENSE: Propietary License * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech). All Rights Reserved. * Copyright (c) 2019-2020 Ramon Santamaria (@raysan5)
* *
* Unauthorized copying of this file, via any medium is strictly prohibited * This software is provided "as-is", without any express or implied warranty. In no event
* This project is proprietary and confidential unless the owner allows * will the authors be held liable for any damages arising from the use of this software.
* usage in any other form by expresely written permission. *
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
@ -37,21 +48,23 @@
typedef struct { typedef struct {
Vector2 position; Vector2 position;
Vector2 size;
bool fileDialogActive; bool fileDialogActive;
bool dirPathEditMode; bool dirPathEditMode;
char dirPathText[256]; char dirPathText[256];
int filesListScrollIndex; int filesListScrollIndex;
bool filesListEditMode; bool filesListEditMode;
int filesListActive; int filesListActive;
bool fileNameEditMode; bool fileNameEditMode;
char fileNameText[256]; char fileNameText[256];
bool SelectFilePressed; bool SelectFilePressed;
bool CancelFilePressed; bool CancelFilePressed;
int fileTypeActive; int fileTypeActive;
int itemFocused;
// Custom state variables (depend on development software) // Custom state variables (depend on development software)
// NOTE: This variables should be added manually if required // NOTE: This variables should be added manually if required
@ -59,10 +72,10 @@ typedef struct {
int dirFilesCount; int dirFilesCount;
char filterExt[256]; char filterExt[256];
char dirPathTextCopy[256]; char dirPathTextCopy[256];
char fileNameTextCopy[256]; char fileNameTextCopy[256];
int prevFilesListActive; int prevFilesListActive;
} GuiFileDialogState; } GuiFileDialogState;
@ -89,7 +102,7 @@ extern "C" { // Prevents name mangling of functions
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
GuiFileDialogState InitGuiFileDialog(void); GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active);
void GuiFileDialog(GuiFileDialogState *state); void GuiFileDialog(GuiFileDialogState *state);
#ifdef __cplusplus #ifdef __cplusplus
@ -128,12 +141,15 @@ typedef struct FileInfo {
int type; int type;
int icon; int icon;
} FileInfo; } FileInfo;
#else
// Filename only
typedef char *FileInfo;
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
char **dirFilesIcon = NULL; FileInfo *dirFilesIcon = NULL;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Internal Module Functions Definition // Internal Module Functions Definition
@ -143,25 +159,28 @@ static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterE
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO) #if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
// List View control for files info with extended parameters // List View control for files info with extended parameters
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active) static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active);
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
GuiFileDialogState InitGuiFileDialog(void) GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active)
{ {
GuiFileDialogState state = { 0 }; GuiFileDialogState state = { 0 };
state.position = (Vector2){ GetScreenWidth()/2 - 480/2, GetScreenHeight()/2 - 305/2 }; // Default dialog size is 440x310
state.size.x = width == -1 ? 440 : width;
state.fileDialogActive = false; state.size.y = height == -1 ? 310 : height;
state.position = (Vector2){ GetScreenWidth()/2 - state.size.x/2, GetScreenHeight()/2 - state.size.y/2 };
state.fileDialogActive = active;
state.dirPathEditMode = false; state.dirPathEditMode = false;
state.filesListActive = -1; state.filesListActive = -1;
state.prevFilesListActive = state.filesListActive; state.prevFilesListActive = state.filesListActive;
state.filesListScrollIndex = 0; state.filesListScrollIndex = 0;
state.fileNameEditMode = false; state.fileNameEditMode = false;
state.SelectFilePressed = false; state.SelectFilePressed = false;
@ -169,58 +188,91 @@ GuiFileDialogState InitGuiFileDialog(void)
state.fileTypeActive = 0; state.fileTypeActive = 0;
strcpy(state.fileNameText, "\0");
// Custom variables initialization // Custom variables initialization
strcpy(state.dirPathText, GetWorkingDirectory()); if (initPath && DirectoryExists(initPath))
{
strcpy(state.dirPathText, initPath);
}
else if (initPath && FileExists(initPath))
{
strcpy(state.dirPathText, GetDirectoryPath(initPath));
strcpy(state.fileNameText, GetFileName(initPath));
}
else strcpy(state.dirPathText, GetWorkingDirectory());
strcpy(state.dirPathTextCopy, state.dirPathText); strcpy(state.dirPathTextCopy, state.dirPathText);
strcpy(state.fileNameTextCopy, state.fileNameText);
strcpy(state.filterExt, "all"); strcpy(state.filterExt, "all");
state.dirFilesCount = 0; state.dirFilesCount = 0;
state.dirFiles = NULL; // NOTE: Loaded lazily on window active state.dirFiles = NULL; // NOTE: Loaded lazily on window active
strcpy(state.fileNameText, "\0");
strcpy(state.fileNameTextCopy, state.fileNameText);
return state; return state;
} }
// Read files in new path
static void FD_RELOAD_DIRPATH(GuiFileDialogState *state)
{
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
RL_FREE(state->dirFiles);
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
state->itemFocused = 0;
}
// Update and draw file dialog
void GuiFileDialog(GuiFileDialogState *state) void GuiFileDialog(GuiFileDialogState *state)
{ {
if (state->fileDialogActive) if (state->fileDialogActive)
{ {
const int winWidth = state->size.x;
const int winHeight = state->size.y;
// Load dirFilesIcon and state->dirFiles lazily on windows open // Load dirFilesIcon and state->dirFiles lazily on windows open
// NOTE: they are automatically unloaded at fileDialog closing // NOTE: they are automatically unloaded at fileDialog closing
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
if (dirFilesIcon == NULL) if (dirFilesIcon == NULL)
{ {
dirFilesIcon = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read dirFilesIcon = (FileInfo *)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(FileInfo)); // Max files to read
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)calloc(MAX_DIR_PATH_LENGTH, 1); // Max file name length for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)calloc(MAX_DIR_PATH_LENGTH, 1); // Max file name length
} }
if (state->dirFiles == NULL) state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt); if (state->dirFiles == NULL)
{
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
for(int f = 0; f < state->dirFilesCount; f++)
{
if (strcmp(state->fileNameText, state->dirFiles[f]) == 0)
{
if (state->filesListActive != f) state->filesListScrollIndex = state->filesListActive = f; // Make it active and visible only on first call
break;
}
}
}
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.85f)); DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.85f));
state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, 480, 310 }, "#198#Select File Dialog"); state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, winWidth, winHeight }, "#198#LuaJIT | Select File Dialog");
if (GuiButton((Rectangle){ state->position.x + 430, state->position.y + 35, 40, 25 }, "< ..")) if (GuiButton((Rectangle){ state->position.x + winWidth - 50, state->position.y + 35, 40, 25 }, "< ..")) // || IsKeyReleased(KEY_DPAD_Y))
{ {
// Move dir path one level up // Move dir path one level up
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText)); strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles()) // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]); FD_RELOAD_DIRPATH(state);
RL_FREE(state->dirFiles);
// Read files in the new path
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
state->filesListActive = -1; state->filesListActive = -1;
strcpy(state->fileNameText, "\0"); strcpy(state->fileNameText, "\0");
strcpy(state->fileNameTextCopy, state->fileNameText); strcpy(state->fileNameTextCopy, state->fileNameText);
} }
if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, 410, 25 }, state->dirPathText, 256, state->dirPathEditMode)) if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, winWidth - 65, 25 }, state->dirPathText, 256, state->dirPathEditMode))
{ {
if (state->dirPathEditMode) if (state->dirPathEditMode)
{ {
@ -228,51 +280,48 @@ void GuiFileDialog(GuiFileDialogState *state)
if (DirectoryExists(state->dirPathText)) if (DirectoryExists(state->dirPathText))
{ {
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles()) // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]); FD_RELOAD_DIRPATH(state);
RL_FREE(state->dirFiles);
// Read files in new path
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
strcpy(state->dirPathTextCopy, state->dirPathText); strcpy(state->dirPathTextCopy, state->dirPathText);
} }
else strcpy(state->dirPathText, state->dirPathTextCopy); else strcpy(state->dirPathText, state->dirPathTextCopy);
} }
state->dirPathEditMode = !state->dirPathEditMode; state->dirPathEditMode = !state->dirPathEditMode;
} }
int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT); int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
int prevElementsHeight = GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT); int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT); GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
GuiSetStyle(LISTVIEW, ELEMENTS_HEIGHT, 24); GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
// TODO: ListViewElements should be aligned left // TODO: ListViewElements should be aligned left
state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, 460, 164 }, dirFilesIcon, state->dirFilesCount, NULL, &state->filesListScrollIndex, state->filesListActive); # if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
FileInfo fileInfo;
state->filesListActive = GuiListViewFiles((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, fileInfo, state->dirFilesCount, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
# else
state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, (const char**)dirFilesIcon, state->dirFilesCount, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
# endif
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment); GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
GuiSetStyle(LISTVIEW, ELEMENTS_HEIGHT, prevElementsHeight); GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive)) if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
//&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A)))
{ {
strcpy(state->fileNameText, state->dirFiles[state->filesListActive]); strcpy(state->fileNameText, state->dirFiles[state->filesListActive]);
if (DirectoryExists(TextFormat("%s\\%s", state->dirPathText, state->fileNameText))) if (DirectoryExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
{ {
if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText)); if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
else strcpy(state->dirPathText, TextFormat("%s\\%s", state->dirPathText, state->fileNameText)); else strcpy(state->dirPathText, TextFormat("%s/%s", strcmp(state->dirPathText, "/")==0 ? "" : state->dirPathText, state->fileNameText));
strcpy(state->dirPathTextCopy, state->dirPathText); strcpy(state->dirPathTextCopy, state->dirPathText);
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles()) // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]); FD_RELOAD_DIRPATH(state);
RL_FREE(state->dirFiles);
// Read files in new path
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
strcpy(state->dirPathTextCopy, state->dirPathText); strcpy(state->dirPathTextCopy, state->dirPathText);
state->filesListActive = -1; state->filesListActive = -1;
strcpy(state->fileNameText, "\0"); strcpy(state->fileNameText, "\0");
strcpy(state->fileNameTextCopy, state->fileNameText); strcpy(state->fileNameTextCopy, state->fileNameText);
@ -280,12 +329,12 @@ void GuiFileDialog(GuiFileDialogState *state)
state->prevFilesListActive = state->filesListActive; state->prevFilesListActive = state->filesListActive;
} }
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 245, 68, 25 }, "File name:"); GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 60, 68, 25 }, "File name:");
if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + 245, 275, 25 }, state->fileNameText, 128, state->fileNameEditMode)) if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 60, winWidth - 200, 25 }, state->fileNameText, 128, state->fileNameEditMode))
{ {
if (state->fileNameText) if (*state->fileNameText)
{ {
// Verify if a valid filename has been introduced // Verify if a valid filename has been introduced
if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText))) if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
@ -301,73 +350,129 @@ void GuiFileDialog(GuiFileDialogState *state)
} }
} }
} }
else else
{ {
strcpy(state->fileNameText, state->fileNameTextCopy); strcpy(state->fileNameText, state->fileNameTextCopy);
} }
} }
state->fileNameEditMode = !state->fileNameEditMode; state->fileNameEditMode = !state->fileNameEditMode;
} }
state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + 275, 275, 25 }, "All files", state->fileTypeActive); state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 30, winWidth - 200, 25 }, "All files", state->fileTypeActive);
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 275, 68, 25 }, "File filter:"); GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 30, 68, 25 }, "File filter:");
state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + 360, state->position.y + 245, 110, 25 }, "Select"); state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + winWidth - 120, state->position.y + winHeight - 60, 110,
#ifdef PLATFORM_DESKTOP
25
#else
25 + 30
#endif
}, "Select");// || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A);
if (state->SelectFilePressed) state->fileDialogActive = false; if (state->SelectFilePressed) state->fileDialogActive = false;
if (GuiButton((Rectangle){ state->position.x + 360, state->position.y + 275, 110, 25 }, "Cancel")) state->fileDialogActive = false; #ifdef PLATFORM_DESKTOP
if (GuiButton((Rectangle){ state->position.x + winWidth - 120, state->position.y + winHeight - 30, 110, 25 }, "Quit")) state->fileDialogActive = false;
#endif
// File dialog has been closed! // File dialog has been closed!
if (!state->fileDialogActive) if (!state->fileDialogActive)
{ {
// RL_FREE dirFiles memory // RL_FREE dirFiles memory
for (int i = 0; i < state->dirFilesCount; i++) for (int i = 0; i < state->dirFilesCount; i++)
{ {
RL_FREE(state->dirFiles[i]); RL_FREE(state->dirFiles[i]);
RL_FREE(dirFilesIcon[i]); RL_FREE(dirFilesIcon[i]);
} }
RL_FREE(state->dirFiles); RL_FREE(state->dirFiles);
RL_FREE(dirFilesIcon); RL_FREE(dirFilesIcon);
dirFilesIcon = NULL; dirFilesIcon = NULL;
state->dirFiles = NULL; state->dirFiles = NULL;
} }
} }
} }
// Compare two files from a directory
static inline int FileCompare(const char *d1, const char *d2, const char *dir)
{
const bool b1 = DirectoryExists(TextFormat("%s/%s", dir, d1));
const bool b2 = DirectoryExists(TextFormat("%s/%s", dir, d2));
if (b1 && !b2) return -1;
if (!b1 && b2) return 1;
if (!FileExists(TextFormat("%s/%s", dir, d1))) return 1;
if (!FileExists(TextFormat("%s/%s", dir, d2))) return -1;
return strcmp(d1, d2);
}
// Read all filenames from directory (supported file types) // Read all filenames from directory (supported file types)
static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt) static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt)
{ {
int validFilesCount = 0; int validFilesCount = 0;
char **validFiles = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read char **validFiles = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) validFiles[i] = (char *)RL_MALLOC(MAX_DIR_PATH_LENGTH); // Max file name length for (int i = 0; i < MAX_DIRECTORY_FILES; i++) validFiles[i] = (char *)RL_MALLOC(MAX_DIR_PATH_LENGTH); // Max file name length
int filterExtCount = 0; int filterExtCount = 0;
const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL); const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL);
bool filterExtensions = true; bool filterExtensions = true;
int dirFilesCount = 0; int dirFilesCount = 0;
char **files = GetDirectoryFiles(dir, &dirFilesCount); char **files = GetDirectoryFiles(dir, &dirFilesCount);
// Sort files and directories: dir by name + files by name
// https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Quicksort#C
if (dirFilesCount > 1)
{
const int MAX = 64;
unsigned int left = 0, stack[64], pos = 0, seed = rand(), len = dirFilesCount;
for (;;)
{
for (; left + 1 < len; len++) // Sort left to len - 1
{
if (pos == MAX) len = stack[pos = 0]; // Stack overflow, reset
char *pivot = files[left + seed%(len - left)]; // Pick random pivot
seed = seed*69069 + 1; // Next pseudo-random number
stack[pos++] = len; // Sort right part later
for (unsigned int right = left - 1;;) // Inner loop: partitioning
{
while (FileCompare(files[++right], pivot, dir) < 0); // Look for greater element
while (FileCompare(pivot, files[--len], dir) < 0); // Look for smaller element
if (right >= len) break; // Partition point found?
char *temp = files[right];
files[right] = files[len]; // The only swap
files[len] = temp;
} // Partitioned, continue left part
}
if (pos == 0) break; // Stack empty?
left = len; // Left to right is sorted
len = stack[--pos]; // Get next range to sort
}
}
if (TextIsEqual(extensions[0], "all")) filterExtensions = false; if (TextIsEqual(extensions[0], "all")) filterExtensions = false;
for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++) for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++)
{ {
if (TextIsEqual(files[i], ".")) continue; if (TextIsEqual(files[i], ".")) continue;
if (!filterExtensions) if (!filterExtensions)
{ {
strcpy(validFiles[validFilesCount], files[i]); strncpy(validFiles[validFilesCount], files[i], MAX_DIR_PATH_LENGTH);
// Only filter files by extensions, directories should be available // Only filter files by extensions, directories should be available
if (DirectoryExists(TextFormat("%s\\%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i])); if (DirectoryExists(TextFormat("%s/%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
else else
{ {
// TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...) // TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...)
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i])); if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i])); else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
} }
@ -386,17 +491,15 @@ static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterE
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i])); if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i])); else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
validFilesCount++; validFilesCount++;
} }
} }
} }
} }
// TODO: Sort files and directories: dir by name + files by name
ClearDirectoryFiles(); ClearDirectoryFiles();
*filesCount = validFilesCount; *filesCount = validFilesCount;
return validFiles; return validFiles;
} }
@ -408,23 +511,23 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
GuiControlState state = guiState; GuiControlState state = guiState;
int itemFocused = (focus == NULL)? -1 : *focus; int itemFocused = (focus == NULL)? -1 : *focus;
int itemSelected = active; int itemSelected = active;
// Check if we need a scroll bar // Check if we need a scroll bar
bool useScrollBar = false; bool useScrollBar = false;
if ((GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING))*count > bounds.height) useScrollBar = true; if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING))*count > bounds.height) useScrollBar = true;
// Define base item rectangle [0] // Define base item rectangle [0]
Rectangle itemBounds = { 0 }; Rectangle itemBounds = { 0 };
itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING); itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING);
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
itemBounds.height = GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT); itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
// Get items on the list // Get items on the list
int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)); int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
if (visibleItems > count) visibleItems = count; if (visibleItems > count) visibleItems = count;
int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
int endIndex = startIndex + visibleItems; int endIndex = startIndex + visibleItems;
@ -434,12 +537,12 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
if ((state != GUI_STATE_DISABLED) && !guiLocked) if ((state != GUI_STATE_DISABLED) && !guiLocked)
{ {
Vector2 mousePoint = GetMousePosition(); Vector2 mousePoint = GetMousePosition();
// Check mouse inside list view // Check mouse inside list view
if (CheckCollisionPointRec(mousePoint, bounds)) if (CheckCollisionPointRec(mousePoint, bounds))
{ {
state = GUI_STATE_FOCUSED; state = GUI_STATE_FOCUSED;
// Check focused and selected item // Check focused and selected item
for (int i = 0; i < visibleItems; i++) for (int i = 0; i < visibleItems; i++)
{ {
@ -449,16 +552,16 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i; if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
break; break;
} }
// Update item rectangle y position for next item // Update item rectangle y position for next item
itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)); itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
} }
if (useScrollBar) if (useScrollBar)
{ {
int wheelMove = GetMouseWheelMove(); int wheelMove = GetMouseWheelMove();
startIndex -= wheelMove; startIndex -= wheelMove;
if (startIndex < 0) startIndex = 0; if (startIndex < 0) startIndex = 0;
else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
@ -467,19 +570,19 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
} }
} }
else itemFocused = -1; else itemFocused = -1;
// Reset item rectangle y to [0] // Reset item rectangle y to [0]
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Draw control // Draw control
//-------------------------------------------------------------------- //--------------------------------------------------------------------
DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha)); DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
// TODO: Draw list view header with file sections: icon+name | size | type | modTime // TODO: Draw list view header with file sections: icon+name | size | type | modTime
// Draw visible items // Draw visible items
for (int i = 0; i < visibleItems; i++) for (int i = 0; i < visibleItems; i++)
{ {
@ -490,9 +593,9 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha)); DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha)); DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha));
} }
// TODO: Draw full file info line: icon+name | size | type | modTime // TODO: Draw full file info line: icon+name | size | type | modTime
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha)); GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
} }
else else
@ -502,7 +605,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
// Draw item selected // Draw item selected
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha)); DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha)); DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha));
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha)); GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
} }
else if ((startIndex + i) == itemFocused) else if ((startIndex + i) == itemFocused)
@ -510,7 +613,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
// Draw item focused // Draw item focused
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha)); DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha)); DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha));
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha)); GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
} }
else else
@ -521,36 +624,36 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
} }
// Update item rectangle y position for next item // Update item rectangle y position for next item
itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)); itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
} }
if (useScrollBar) if (useScrollBar)
{ {
Rectangle scrollBarBounds = { Rectangle scrollBarBounds = {
bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
}; };
// Calculate percentage of visible items and apply same percentage to scrollbar // Calculate percentage of visible items and apply same percentage to scrollbar
float percentVisible = (float)(endIndex - startIndex)/count; float percentVisible = (float)(endIndex - startIndex)/count;
float sliderSize = bounds.height*percentVisible; float sliderSize = bounds.height*percentVisible;
int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_SIZE); // Save default slider size int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH); // Save default slider size
int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
GuiSetStyle(SCROLLBAR, SLIDER_SIZE, sliderSize); // Change slider size GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, sliderSize); // Change slider size
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
GuiSetStyle(SCROLLBAR, SLIDER_SIZE, prevSliderSize); // Reset slider size to default GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, prevSliderSize); // Reset slider size to default
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
if (focus != NULL) *focus = itemFocused; if (focus != NULL) *focus = itemFocused;
if (scrollIndex != NULL) *scrollIndex = startIndex; if (scrollIndex != NULL) *scrollIndex = startIndex;
return itemSelected; return itemSelected;
} }
#endif // USE_CUSTOM_LISTVIEW_FILEINFO #endif // USE_CUSTOM_LISTVIEW_FILEINFO

View File

@ -11,7 +11,7 @@
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech) * Copyright (c) 2020 Ramon Santamaria (@raysan5)
* *
********************************************************************************************/ ********************************************************************************************/
@ -54,7 +54,7 @@ int main(int argc, char *argv[0])
bool imageLoaded = false; bool imageLoaded = false;
float imageScale = 1.0f; float imageScale = 1.0f;
Rectangle imageRec = { 0.0f }; Rectangle imageRec = { 0 };
bool btnExport = false; bool btnExport = false;

View File

@ -11,7 +11,7 @@
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech) * Copyright (c) 2020 Ramon Santamaria (@raysan5)
* *
**********************************************************************************************/ **********************************************************************************************/
@ -190,10 +190,10 @@ int main()
GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 50, 75, 20 }, FormatText("%i bytes", dataSize)); GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 50, 75, 20 }, FormatText("%i bytes", dataSize));
GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 85, 180, 80 }, "Resolution"); GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 85, 180, 80 }, "Resolution");
GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 100, 33, 25 }, "Width:"); GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 100, 33, 25 }, "Width:");
if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 100, 80, 25 }, &widthValue, 0, 8192, widthEditMode)) widthEditMode = !widthEditMode; if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 100, 80, 25 }, NULL, &widthValue, 0, 8192, widthEditMode)) widthEditMode = !widthEditMode;
GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 100, 30, 25 }, "pixels"); GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 100, 30, 25 }, "pixels");
GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 130, 33, 25 }, "Height:"); GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 130, 33, 25 }, "Height:");
if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 130, 80, 25 }, &heightValue, 0, 8192, heightEditMode)) heightEditMode = !heightEditMode; if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 130, 80, 25 }, NULL, &heightValue, 0, 8192, heightEditMode)) heightEditMode = !heightEditMode;
GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 130, 30, 25 }, "pixels"); GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 130, 30, 25 }, "pixels");
GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 180, 180, 160 }, "Pixel Format"); GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 180, 180, 160 }, "Pixel Format");
pixelFormatActive = GuiComboBox((Rectangle){ windowOffset.x + 20, windowOffset.y + 195, 160, 25 }, TextJoin(pixelFormatTextList, 8, ";"), pixelFormatActive); pixelFormatActive = GuiComboBox((Rectangle){ windowOffset.x + 20, windowOffset.y + 195, 160, 25 }, TextJoin(pixelFormatTextList, 8, ";"), pixelFormatActive);
@ -208,7 +208,7 @@ int main()
GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 355, 180, 50 }, "Header"); GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 355, 180, 50 }, "Header");
GuiLabel((Rectangle){ windowOffset.x + 25, windowOffset.y + 370, 27, 25 }, "Size:"); GuiLabel((Rectangle){ windowOffset.x + 25, windowOffset.y + 370, 27, 25 }, "Size:");
if (GuiValueBox((Rectangle){ windowOffset.x + 55, windowOffset.y + 370, 85, 25 }, &headerSizeValue, 0, 10000, headerSizeEditMode)) headerSizeEditMode = !headerSizeEditMode; if (GuiValueBox((Rectangle){ windowOffset.x + 55, windowOffset.y + 370, 85, 25 }, NULL, &headerSizeValue, 0, 10000, headerSizeEditMode)) headerSizeEditMode = !headerSizeEditMode;
GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 370, 30, 25 }, "bytes"); GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 370, 30, 25 }, "bytes");
btnLoadPressed = GuiButton((Rectangle){ windowOffset.x + 10, windowOffset.y + 420, 180, 30 }, "Import RAW"); btnLoadPressed = GuiButton((Rectangle){ windowOffset.x + 10, windowOffset.y + 420, 180, 30 }, "Import RAW");

View File

@ -11,7 +11,7 @@
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 raylib technologies (@raylibtech) * Copyright (c) 2020 Ramon Santamaria (@raysan5)
* *
**********************************************************************************************/ **********************************************************************************************/

View File

@ -0,0 +1,867 @@
/*******************************************************************************************
*
* PropertyListControl v1.0.1 - A custom control that displays a set of properties as a list
*
* UPDATES: last updated - 10 march 2020 (v1.0.1)
* v1.0.1 - Made it work with latest raygui version
* - Added `GuiDMSaveProperties()` for saving properties to a text file
* - A `GuiDMLoadProperties()` is planed but not implemented yet
* - Added a section property that can work as a way to group multiple properties
* - Fixed issue with section not having the correct height
* v1.0.0 - Initial release
*
*
* MODULE USAGE:
* #define GUI_PROPERTY_LIST_IMPLEMENTATION
* #include "dm_property_list.h"
*
* INIT: GuiDMProperty props[] = { // initialize a set of properties first
PCOLOR(),
PINT(),
PFLOAT(),
...
};
* DRAW: GuiDMPropertyList(bounds, props, sizeof(props)/sizeof(props[0]), ...);
*
*
* NOTE: This module also contains 2 extra controls used internally by the property list
* - GuiDMValueBox() - a value box that supports displaying float values
* - GuiDMSpinner() - a `better` GuiSpinner()
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2020 Vlad Adrian (@Demizdor - https://github.com/Demizdor).
*
**********************************************************************************************/
#include "raylib.h"
// WARNING: raygui implementation is expected to be defined before including this header
#undef RAYGUI_IMPLEMENTATION
#include "../../src/raygui.h"
#ifndef GUI_PROPERTY_LIST_H
#define GUI_PROPERTY_LIST_H
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// A bunch of usefull macros for modifying the flags of each property
// Set flag `F` of property `P`. `P` must be a pointer!
#define PROP_SET_FLAG(P, F) ((P)->flags |= (F))
// Clear flag `F` of property `P`. `P` must be a pointer!
#define PROP_CLEAR_FLAG(P, F) ((P)->flags &= ~(F))
// Toggles flag `F` of property `P`. `P` must be a pointer!
#define PROP_TOGGLE_FLAG(P, F) ((P)->flags ^= (F))
// Checks if flag `F` of property `P` is set . `P` must be a pointer!
#define PROP_CHECK_FLAG(P, F) ((P)->flags & (F))
// Some usefull macros for creating properties
// Create a bool property with name `N`, flags `F` and value `V`
#define PBOOL(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_BOOL, F, .value.vbool = V}
// Create a int property with name `N`, flags `F` and value `V`
#define PINT(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_INT, F, .value.vint = {V,0,0,1}}
// Create a ranged int property within `MIN` and `MAX` with name `N`, flags `F` value `V`.
// Pressing the spinner buttons will increase/decrease the value by `S`.
#define PINT_RANGE(N, F, V, S, MIN, MAX) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_INT, F, .value.vint = {V,MIN,MAX,S}}
// Create a float property with name `N`, flags `F` and value `V`
#define PFLOAT(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_FLOAT, F, .value.vfloat = {V,0.f,0.f,1.0f,3}}
// Create a ranged float property within `MIN` and `MAX` with name `N`, flags `F` value `V` with `P` decimal digits to show.
// Pressing the spinner buttons will increase/decrease the value by `S`.
#define PFLOAT_RANGE(N, F, V, S, P, MIN, MAX) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_FLOAT, F, .value.vfloat = {V,MIN,MAX,S,P}}
// Create a text property with name `N`, flags `F` value `V` and max text size `S`
#define PTEXT(N, F, V, S) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_TEXT, F, .value.vtext = {V, S} }
// Create a text property with name `N`, flags `F` value `V` and max text size `S`
#define PSELECT(N, F, V, A) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_SELECT, F, .value.vselect = {V, A} }
// Create a 2D vector property with name `N`, flags `F` and the `X`, `Y` coordinates
#define PVEC2(N, F, X, Y) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR2, F, .value.v2 = {X, Y} }
// Create a 3D vector property with name `N`, flags `F` and the `X`, `Y`, `Z` coordinates
#define PVEC3(N, F, X, Y, Z) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR3, F, .value.v3 = {X, Y, Z} }
// Create a 4D vector property with name `N`, flags `F` and the `X`, `Y`, `Z`, `W` coordinates
#define PVEC4(N, F, X, Y, Z, W) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR4, F, .value.v4 = {X, Y, Z, W} }
// Create a rectangle property with name `N`, flags `F`, `X`, `Y` coordinates and `W` and `H` size
#define PRECT(N, F, X, Y, W, H) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_RECT, F, .value.vrect = {X, Y, W, H} }
// Create a 3D vector property with name `N`, flags `F` and the `R`, `G`, `B`, `A` channel values
#define PCOLOR(N, F, R, G, B, A) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_COLOR, F, .value.vcolor = {R, G, B, A} }
// Create a collapsable section named `N` with `F` flags and the next `C` properties as children.
// !! A section cannot hold another section as a child !!
#define PSECTION(N, F, C) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_SECTION, F, .value.vsection = (C)}
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
enum GuiDMPropertyTypes {
GUI_PROP_BOOL = 0,
GUI_PROP_INT,
GUI_PROP_FLOAT,
GUI_PROP_TEXT,
GUI_PROP_SELECT,
GUI_PROP_VECTOR2,
GUI_PROP_VECTOR3,
GUI_PROP_VECTOR4,
GUI_PROP_RECT,
GUI_PROP_COLOR,
GUI_PROP_SECTION,
};
enum GuiDMPropertyFlags {
GUI_PFLAG_COLLAPSED = 1 << 0, // is the property expanded or collapsed?
GUI_PFLAG_DISABLED = 1 << 1, // is this property disabled or enabled?
};
// Data structure for each property
typedef struct {
char* name;
short type;
short flags;
union {
bool vbool;
struct { int val; int min; int max; int step; } vint;
struct { float val; float min; float max; float step; int precision; } vfloat;
struct { char* val; int size; } vtext;
struct { char* val; int active; } vselect;
int vsection;
Vector2 v2;
Vector3 v3;
Vector4 v4;
Rectangle vrect;
Color vcolor;
} value;
} GuiDMProperty;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
// A more advanced `GuiValueBox()` supporting float/int values with specified `precision`, cursor movements, cut/copy/paste and
// other keybord shortcuts. Needed by `GuiDMSpinner()` !!
// `precision` should be between 1-7 for float values and 0 for int values (maybe 15 for doubles but that was not tested)
// WARNING: The bounds should be set big enough else the text will overflow and things will break
// WARNING: Sometimes the last decimal value could differ, this is probably due to rounding
double GuiDMValueBox(Rectangle bounds, double value, double minValue, double maxValue, int precision, bool editMode);
// A more advanced `GuiSpinner()` using `GuiDMValueBox()` for displaying the values.
// This was needed because `GuiSpinner()` can't display float values and editing values is somewhat hard.
// This is by no means perfect but should be more user friendly than the default control provided by raygui.
double GuiDMSpinner(Rectangle bounds, double value, double minValue, double maxValue, double step, int precision, bool editMode);
// Works just like `GuiListViewEx()` but with an array of properties instead of text.
void GuiDMPropertyList(Rectangle bounds, GuiDMProperty* props, int count, int* focus, int* scrollIndex);
// Handy function to save properties to a file. Returns false on failure or true otherwise.
bool GuiDMSaveProperties(const char* file, GuiDMProperty* props, int count);
#ifdef __cplusplus
}
#endif
#endif // GUI_PROPERTY_LIST_H
/***********************************************************************************
*
* GUI_PROPERTY_LIST_IMPLEMENTATION
*
************************************************************************************/
#if defined(GUI_PROPERTY_LIST_IMPLEMENTATION)
#include "../../src/raygui.h"
#include <stdlib.h> // for calloc()
#include <string.h> // for memmove(), strlen()
#include <stdio.h> // for sscanf(), snprintf()
#ifndef __cplusplus
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h> // for bool if >= C99
#endif
#endif
double GuiDMValueBox(Rectangle bounds, double value, double minValue, double maxValue, int precision, bool editMode) {
// FIXME: Hope all those `memmove()` functions are correctly used so we won't leak memory or overflow the buffer !!!
static int framesCounter = 0; // Required for blinking cursor
static int cursor = 0; // Required for tracking the cursor position (only for a single active valuebox)
enum {cursorTimer = 6, maxChars = 31, textPadding = 2};
GuiControlState state = GuiGetState();
// Make sure value is in range
if(maxValue != minValue){
if(value < minValue) value = minValue;
if(value > maxValue) value = maxValue;
}
char textValue[maxChars + 1] = "\0";
snprintf(textValue, maxChars, "%.*f", precision, value); // NOTE: use `snprintf` here so we don't overflow the buffer
int len = strlen(textValue);
bool valueHasChanged = false;
// Update control
//--------------------------------------------------------------------
if ((state != GUI_STATE_DISABLED) && !guiLocked)
{
if (editMode)
{
// Make sure cursor position is correct
if(cursor > len) cursor = len;
if(cursor < 0) cursor = 0;
state = GUI_STATE_PRESSED;
framesCounter++;
if(IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (framesCounter%cursorTimer == 0))) {
// MOVE CURSOR TO RIGHT
++cursor;
framesCounter = 0;
} else if(IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (framesCounter%cursorTimer == 0))) {
// MOVE CURSOR TO LEFT
--cursor;
framesCounter = 0;
} else if (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (framesCounter%cursorTimer) == 0)) {
// HANDLE BACKSPACE
if(cursor > 0) {
if(textValue[cursor-1] != '.') {
if(cursor < len )
memmove(&textValue[cursor-1], &textValue[cursor], len-cursor);
textValue[len - 1] = '\0';
valueHasChanged = true;
}
--cursor;
}
framesCounter = 0;
} else if (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (framesCounter%cursorTimer) == 0)) {
// HANDLE DEL
if(len > 0 && cursor < len && textValue[cursor] != '.') {
memmove(&textValue[cursor], &textValue[cursor+1], len-cursor);
textValue[len] = '\0';
len -= 1;
valueHasChanged = true;
}
} else if (IsKeyPressed(KEY_HOME)) {
// MOVE CURSOR TO START
cursor = 0;
} else if (IsKeyPressed(KEY_END)) {
// MOVE CURSOR TO END
cursor = len;
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) {
// COPY
SetClipboardText(textValue);
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_X)) {
// CUT
SetClipboardText(textValue);
textValue[0] = '\0';
cursor = len = 0;
value = 0.0; // set it to 0 and pretend the value didn't change
} else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) {
// PASTE
const char* clip = GetClipboardText();
int clipLen = strlen(clip);
clipLen = clipLen > maxChars ? maxChars : clipLen;
memcpy(textValue, clip, clipLen);
len = clipLen;
textValue[len] = '\0';
valueHasChanged = true;
}
else {
// HANDLE KEY PRESS
int key = GetKeyPressed();
if( ((len < maxChars) && (key >= 48) && (key <= 57)) || (key == 46) || (key == 45) ) // only allow 0..9, minus(-) and dot(.)
{
if(precision != 0 && cursor < len) { // when we have decimals we can't insert at the end
memmove(&textValue[cursor], &textValue[cursor-1], len+1-cursor);
textValue[len+1] = '\0';
textValue[cursor] = (char)key;
cursor++;
valueHasChanged = true;
}
else if(precision == 0) {
if(cursor < len) memmove(&textValue[cursor], &textValue[cursor-1], len+1-cursor);
len += 1;
textValue[len+1] = '\0';
textValue[cursor] = (char)key;
cursor++;
valueHasChanged = true;
}
}
}
// Make sure cursor position is correct
if(cursor > len) cursor = len;
if(cursor < 0) cursor = 0;
}
else
{
if (CheckCollisionPointRec(GetMousePosition(), bounds))
{
state = GUI_STATE_FOCUSED;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) framesCounter = 0;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
DrawRectangleLinesEx(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha));
Rectangle textBounds = {bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH) + textPadding, bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH),
bounds.width - 2*(GuiGetStyle(VALUEBOX, BORDER_WIDTH) + textPadding), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};
int textWidth = GetTextWidth(textValue);
if(textWidth > textBounds.width) textBounds.width = textWidth;
if (state == GUI_STATE_PRESSED)
{
DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)), guiAlpha));
// Draw blinking cursor
// NOTE: ValueBox internal text is always centered
if (editMode && ((framesCounter/20)%2 == 0)) {
// Measure text until the cursor
int textWidthCursor = -2;
if(cursor > 0) {
char c = textValue[cursor];
textValue[cursor] = '\0';
textWidthCursor = GetTextWidth(textValue);
textValue[cursor] = c;
}
//DrawRectangle(bounds.x + textWidthCursor + textPadding + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
DrawRectangle(bounds.x + textWidthCursor + (int)((bounds.width - textWidth - textPadding)/2.0f) + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
}
}
else if (state == GUI_STATE_DISABLED)
{
DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)), guiAlpha));
}
GuiDrawText(textValue, textBounds, GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
value = valueHasChanged ? strtod(textValue, NULL) : value;
// Make sure value is in range
if(maxValue != minValue){
if(value < minValue) value = minValue;
if(value > maxValue) value = maxValue;
}
return value;
}
double GuiDMSpinner(Rectangle bounds, double value, double minValue, double maxValue, double step, int precision, bool editMode) {
GuiControlState state = GuiGetState();
Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_PADDING), bounds.y,
bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_PADDING)), bounds.height };
Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
// Update control
//--------------------------------------------------------------------
if ((state != GUI_STATE_DISABLED) && !guiLocked)
{
Vector2 mousePoint = GetMousePosition();
// Check spinner state
if (CheckCollisionPointRec(mousePoint, bounds))
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
else state = GUI_STATE_FOCUSED;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// Draw value selector custom buttons
// NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH));
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
#if defined(RAYGUI_SUPPORT_ICONS)
if (GuiButton(leftButtonBound, GuiIconText(RICON_ARROW_LEFT_FILL, NULL))) value -= step;
if (GuiButton(rightButtonBound, GuiIconText(RICON_ARROW_RIGHT_FILL, NULL))) value += step;
#else
if (GuiButton(leftButtonBound, "<")) value -= step;
if (GuiButton(rightButtonBound, ">")) value += step;
#endif
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
value = GuiDMValueBox(spinner, value, minValue, maxValue, precision, editMode);
return value;
}
void GuiDMPropertyList(Rectangle bounds, GuiDMProperty* props, int count, int* focus, int* scrollIndex) {
#ifdef RAYGUI_SUPPORT_ICONS
#define PROPERTY_COLLAPSED_ICON "#120#"
#define PROPERTY_EXPANDED_ICON "#121#"
#else
#define PROPERTY_COLLAPSED_ICON "+"
#define PROPERTY_EXPANDED_ICON "-"
#endif
#define PROPERTY_PADDING 6
#define PROPERTY_ICON_SIZE 16
#define PROPERTY_DECIMAL_DIGITS 3 //how many digits to show (used only for the vector properties)
// NOTE: Using ListView style for everything !!
GuiControlState state = GuiGetState();
int propFocused = (focus == NULL)? -1 : *focus;
int scroll = *scrollIndex > 0 ? 0 : *scrollIndex; // NOTE: scroll should always be negative or 0
// Each property occupies a certain number of slots, highly synchronized with the properties enum (GUI_PROP_BOOL ... GUI_PROP_SECTION)
// NOTE: If you add a custom property type make sure to add the number of slots it occupies here !!
const int propSlots[] = {1,1,1,2,1,3,4,5,5,5,1};
Rectangle absoluteBounds = {0}; // total bounds for all of the properties (unclipped)
// We need to loop over all the properties to get total height so we can see if we need a scrollbar or not
for(int p=0; p<count; ++p) {
// Calculate height of this property (properties can occupy 1 or more slots)
int height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
if(props[p].type < (sizeof(propSlots)/sizeof(propSlots[0]))) {
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) height = propSlots[props[p].type]*GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
if(props[p].type == GUI_PROP_SECTION && (PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED))) p += props[p].value.vsection; // skip slots for collapsed section
}
absoluteBounds.height += height+1;
}
// Check if we need a scrollbar and adjust bounds when necesary
bool useScrollBar = absoluteBounds.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) ? true : false;
if(!useScrollBar && scroll != 0) scroll = 0; // make sure scroll is 0 when there's no scrollbar
Rectangle scrollBarBounds = {bounds.x + GuiGetStyle(LISTVIEW, BORDER_WIDTH), bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH),
GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)};
absoluteBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
absoluteBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + scroll;
absoluteBounds.width = bounds.width - 2*(GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH));
if(useScrollBar) {
if(GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)
absoluteBounds.x += GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // scrollbar is on the LEFT, adjust bounds
else
scrollBarBounds.x = bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // scrollbar is on the RIGHT
absoluteBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // adjust width to fit the scrollbar
}
int maxScroll = absoluteBounds.height + 2*(GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH))-bounds.height;
// Update control
//--------------------------------------------------------------------
Vector2 mousePos = GetMousePosition();
// NOTE: most of the update code is actually done in the draw control section
if ((state != GUI_STATE_DISABLED) && !guiLocked) {
if(!CheckCollisionPointRec(mousePos, bounds)) {
propFocused = -1;
}
if (useScrollBar)
{
int wheelMove = GetMouseWheelMove();
scroll += wheelMove*count;
if(-scroll > maxScroll) scroll = -maxScroll;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha) ); // Draw background
DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha)); // Draw border
BeginScissorMode(absoluteBounds.x, bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), absoluteBounds.width, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH));
int currentHeight = 0;
for(int p=0; p<count; ++p)
{
int height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
if(props[p].type < (sizeof(propSlots)/sizeof(propSlots[0])) && !PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) )
height = propSlots[props[p].type]*GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); // get property height based on how many slots it occupies
// Even with scissor mode on, draw only properties that we can see (comment out both BeginScissorMode() / EndScissorMode() to see this)
if(absoluteBounds.y + currentHeight + height >= bounds.y && absoluteBounds.y + currentHeight <= bounds.y + bounds.height)
{
Rectangle propBounds = {absoluteBounds.x, absoluteBounds.y + currentHeight, absoluteBounds.width, height};
Color textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha);
int propState = GUI_STATE_NORMAL;
// Get the state of this property and do some initial drawing
if(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_DISABLED)) {
propState = GUI_STATE_DISABLED;
propBounds.height += 1;
DrawRectangleRec(propBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
propBounds.height -= 1;
textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha);
} else {
if(CheckCollisionPointRec(mousePos, propBounds) && !guiLocked) {
if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
propState = GUI_STATE_PRESSED;
//DrawRectangleRec(propRect, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha);
} else {
propState = GUI_STATE_FOCUSED;
propFocused = p;
//DrawRectangleRec(propRect, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha);
}
} else propState = GUI_STATE_NORMAL;
}
if(propState == GUI_STATE_DISABLED) GuiSetState(propState);
switch(props[p].type)
{
case GUI_PROP_BOOL: {
// draw property name
GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
if(propState == GUI_STATE_PRESSED) props[p].value.vbool = !props[p].value.vbool; // toggle the property value when clicked
// draw property value
const bool locked = guiLocked;
GuiLock(); // lock the checkbox since we changed the value manually
GuiCheckBox((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + height/4, height/2, height/2}, props[p].value.vbool ? "Yes" : "No", props[p].value.vbool);
if(!locked) GuiUnlock(); // only unlock when needed
} break;
case GUI_PROP_INT:
// draw property name
GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw property value
props[p].value.vint.val = GuiDMSpinner((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
props[p].value.vint.val, props[p].value.vint.min, props[p].value.vint.max, props[p].value.vint.step, 0, (propState == GUI_STATE_FOCUSED) );
break;
case GUI_PROP_FLOAT:
// draw property name
GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw property value
props[p].value.vfloat.val = GuiDMSpinner((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
props[p].value.vfloat.val, props[p].value.vfloat.min, props[p].value.vfloat.max, props[p].value.vfloat.step, props[p].value.vfloat.precision, (propState == GUI_STATE_FOCUSED) );
break;
case GUI_PROP_TEXT: {
Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
// Collapse/Expand property on click
if((propState == GUI_STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
// draw property name
GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(TextFormat("%i/%i", strlen(props[p].value.vtext.val), props[p].value.vtext.size), (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw property value
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED))
GuiTextBox((Rectangle){propBounds.x, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2}, props[p].value.vtext.val, props[p].value.vtext.size, (propState == GUI_STATE_FOCUSED));
} break;
case GUI_PROP_SELECT: {
// TODO: Create a custom dropdownbox control instead of using the raygui combobox
// draw property name
GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw property value
props[p].value.vselect.active = GuiComboBox((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
props[p].value.vselect.val, props[p].value.vselect.active);
} break;
case GUI_PROP_VECTOR2: case GUI_PROP_VECTOR3: case GUI_PROP_VECTOR4: {
Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
// Collapse/Expand property on click
if((propState == GUI_STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
const char* fmt = "";
if(props[p].type == GUI_PROP_VECTOR2) fmt = TextFormat("[%.0f, %.0f]", props[p].value.v2.x, props[p].value.v2.y);
else if(props[p].type == GUI_PROP_VECTOR3) fmt = TextFormat("[%.0f, %.0f, %.0f]", props[p].value.v3.x, props[p].value.v3.y, props[p].value.v3.z);
else fmt = TextFormat("[%.0f, %.0f, %.0f, %.0f]", props[p].value.v4.x, props[p].value.v4.y, props[p].value.v4.z, props[p].value.v4.w);
// draw property name
GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(fmt, (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw X, Y, Z, W values (only when expanded)
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GetTextWidth("A"), slotBounds.height};
Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, propBounds.width-lblBounds.width-2*PROPERTY_PADDING, slotBounds.height};
GuiDrawText("X", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.v2.x = GuiDMSpinner(valBounds, props[p].value.v2.x, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
GuiDrawText("Y", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.v2.y = GuiDMSpinner(valBounds, props[p].value.v2.y, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
if(props[p].type >= GUI_PROP_VECTOR3) {
GuiDrawText("Z", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.v3.z = GuiDMSpinner(valBounds, props[p].value.v3.z, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
}
if(props[p].type >= GUI_PROP_VECTOR4) {
GuiDrawText("W", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.v4.w = GuiDMSpinner(valBounds, props[p].value.v4.w, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
}
}
} break;
case GUI_PROP_RECT:{
Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
// Collapse/Expand property on click
if((propState == GUI_STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
// draw property name
GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(TextFormat("[%.0f, %.0f, %.0f, %.0f]", props[p].value.vrect.x, props[p].value.vrect.y, props[p].value.vrect.width, props[p].value.vrect.height),
(Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw X, Y, Width, Height values (only when expanded)
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GetTextWidth("Height"), slotBounds.height};
Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, propBounds.width-lblBounds.width-2*PROPERTY_PADDING, slotBounds.height};
GuiDrawText("X", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vrect.x = GuiDMSpinner(valBounds, props[p].value.vrect.x, 0.0, 0.0, 1.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
GuiDrawText("Y", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vrect.y = GuiDMSpinner(valBounds, props[p].value.vrect.y, 0.0, 0.0, 1.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
GuiDrawText("Width", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vrect.width = GuiDMSpinner(valBounds, props[p].value.vrect.width, 0.0, 0.0, 1.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = slotBounds.y;
GuiDrawText("Height", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vrect.height = GuiDMSpinner(valBounds, props[p].value.vrect.height, 0.0, 0.0, 1.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
}
} break;
case GUI_PROP_COLOR: {
Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
// Collapse/Expand property on click
if((propState == GUI_STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
// draw property name
GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y+1, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2}, GUI_TEXT_ALIGN_LEFT, textColor);
DrawLineEx( (Vector2){propBounds.x+propBounds.width/2, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 5}, (Vector2){propBounds.x+propBounds.width, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 5}, 6.0f, props[p].value.vcolor);
const char* fmt = TextFormat("#%02X%02X%02X%02X", props[p].value.vcolor.r, props[p].value.vcolor.g, props[p].value.vcolor.b, props[p].value.vcolor.a);
char clip[10] = "\0";
memcpy(clip, fmt, 10*sizeof(char)); // copy to temporary buffer since we can't be sure when TextFormat() will be called again and our text will be overwritten
GuiDrawText(fmt, (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw R, G, B, A values (only when expanded)
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GetTextWidth("A"), slotBounds.height};
Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, GetTextWidth("000000"), slotBounds.height};
Rectangle sbarBounds = { valBounds.x + valBounds.width + PROPERTY_PADDING, slotBounds.y, slotBounds.width - 3*PROPERTY_PADDING - lblBounds.width - valBounds.width, slotBounds.height };
if(sbarBounds.width <= GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2) valBounds.width = propBounds.width-lblBounds.width-2*PROPERTY_PADDING; // hide slider when no space
// save current scrollbar style
int tmpSliderPadding = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING);
int tmpPadding = GuiGetStyle(SCROLLBAR, SCROLL_PADDING);
int tmpBorder = GuiGetStyle(SCROLLBAR, BORDER_WIDTH);
int tmpSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
int tmpArrows = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE);
Color tmpBG1 = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED));
// set a custom scrollbar style
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 3);
GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 10);
GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 6);
GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, GuiGetStyle(DEFAULT, BACKGROUND_COLOR)); // disable scrollbar background
GuiDrawText("R", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vcolor.r = GuiDMValueBox(valBounds, props[p].value.vcolor.r, 0.0, 255.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
props[p].value.vcolor.r = GuiScrollBar(sbarBounds, props[p].value.vcolor.r, 0, 255);
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
GuiDrawText("G", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vcolor.g = GuiDMValueBox(valBounds, props[p].value.vcolor.g, 0.0, 255.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
props[p].value.vcolor.g = GuiScrollBar(sbarBounds, props[p].value.vcolor.g, 0, 255);
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
GuiDrawText("B", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vcolor.b = GuiDMValueBox(valBounds, props[p].value.vcolor.b, 0.0, 255.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
props[p].value.vcolor.b = GuiScrollBar(sbarBounds, props[p].value.vcolor.b, 0, 255);
slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
GuiDrawText("A", lblBounds, GUI_TEXT_ALIGN_LEFT, textColor);
props[p].value.vcolor.a = GuiDMValueBox(valBounds, props[p].value.vcolor.a, 0.0, 255.0, 0, (propState == GUI_STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
props[p].value.vcolor.a = GuiScrollBar(sbarBounds, props[p].value.vcolor.a, 0, 255);
// load saved scrollbar style
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, tmpSliderPadding);
GuiSetStyle(SCROLLBAR, SCROLL_PADDING, tmpPadding);
GuiSetStyle(SCROLLBAR, BORDER_WIDTH, tmpBorder);
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, tmpSliderSize);
GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, tmpArrows);
GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, ColorToInt(tmpBG1));
}
// support COPY/PASTE (need to do this here since GuiDMValueBox() also has COPY/PASTE so we need to overwrite it)
if((propState == GUI_STATE_FOCUSED)) {
if(IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C))
SetClipboardText(clip);
else if(IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)){
unsigned int a = props[p].value.vcolor.a, r = props[p].value.vcolor.r, g=props[p].value.vcolor.g, b=props[p].value.vcolor.b;
sscanf(GetClipboardText(), "#%02X%02X%02X%02X", &r, &g, &b, &a);
props[p].value.vcolor.r=r; props[p].value.vcolor.g=g; props[p].value.vcolor.b=b; props[p].value.vcolor.a=a;
}
}
} break;
case GUI_PROP_SECTION: {
Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
// Collapse/Expand section on click
if( (propState == GUI_STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds) )
PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
GuiDrawText(PROPERTY_EXPANDED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_CENTER, textColor);
} else {
GuiDrawText(PROPERTY_COLLAPSED_ICON, titleBounds, GUI_TEXT_ALIGN_LEFT, textColor);
GuiDrawText(TextFormat("%s [%i]", props[p].name, props[p].value.vsection), (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_CENTER, textColor);
}
} break;
// NOTE: Add your custom property here !!
default: {
// draw property name
GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, GUI_TEXT_ALIGN_LEFT, textColor);
// draw property type
GuiDrawText(TextFormat("TYPE %i", props[p].type), (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, GUI_TEXT_ALIGN_LEFT, textColor);
} break;
} // end of switch()
GuiSetState(state);
}
currentHeight += height + 1;
// Skip collapsed section. Don't put this code inside the switch !!
if(props[p].type == GUI_PROP_SECTION && (PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED))) p += props[p].value.vsection;
} // end for
EndScissorMode();
if(useScrollBar) {
scroll = -GuiScrollBar(scrollBarBounds, -scroll, 0, maxScroll);
*scrollIndex = scroll;
}
//--------------------------------------------------------------------
if(focus != NULL) *focus = propFocused;
}
bool GuiDMSaveProperties(const char* file, GuiDMProperty* props, int count) {
if(file == NULL || props == NULL) return false;
if(count == 0) return true;
FILE* f = fopen(file, "w");
if(f == NULL) return false;
// write header
fprintf(f, "#\n# Property types:\n"
"# b <name> <flags> <value> // Bool\n"
"# i <name> <flags> <value> <min> <max> <step> // Int\n"
"# f <name> <flags> <value> <min> <max> <step> <precision> // Float\n"
"# t <name> <flags> <value> <edit_length> // Text\n"
"# l <name> <flags> <value> <active> // Select\n"
"# g <name> <flags> <value> // Section (Group)\n"
"# v2 <name> <flags> <x> <y> // Vector 2D\n"
"# v3 <name> <flags> <x> <y> <z> // Vector 3D\n"
"# v4 <name> <flags> <x> <y> <z> <w> // Vector 4D\n"
"# r <name> <flags> <x> <y> <width> <height> // Rectangle\n"
"# c <name> <flags> <r> <g> <b> <a> // Color\n"
"#\n\n");
for(int p=0; p<count; ++p)
{
switch(props[p].type) {
case GUI_PROP_BOOL: fprintf(f, "b %s %i %i\n", props[p].name, (int)props[p].flags, (int)props[p].value.vbool);
break;
case GUI_PROP_INT: fprintf(f, "i %s %i %i %i %i %i\n", props[p].name, (int)props[p].flags, props[p].value.vint.val, props[p].value.vint.min,
props[p].value.vint.max, props[p].value.vint.step);
break;
case GUI_PROP_FLOAT: fprintf(f, "f %s %i %f %f %f %f %i\n", props[p].name, (int)props[p].flags, props[p].value.vfloat.val, props[p].value.vfloat.min,
props[p].value.vfloat.max, props[p].value.vfloat.step, props[p].value.vfloat.precision);
break;
case GUI_PROP_TEXT: fprintf(f, "t %s %i %s %i\n", props[p].name, (int)props[p].flags, props[p].value.vtext.val, props[p].value.vtext.size);
break;
case GUI_PROP_SELECT: fprintf(f, "l %s %i %s %i\n", props[p].name, (int)props[p].flags, props[p].value.vselect.val, props[p].value.vselect.active);
break;
case GUI_PROP_SECTION: fprintf(f, "g %s %i %i\n", props[p].name, (int)props[p].flags, props[p].value.vsection);
break;
case GUI_PROP_VECTOR2: fprintf(f, "v2 %s %i %f %f\n", props[p].name, (int)props[p].flags, props[p].value.v2.x, props[p].value.v2.y);
break;
case GUI_PROP_VECTOR3: fprintf(f, "v3 %s %i %f %f %f\n", props[p].name, (int)props[p].flags, props[p].value.v3.x, props[p].value.v3.y, props[p].value.v3.z);
break;
case GUI_PROP_VECTOR4: fprintf(f, "v4 %s %i %f %f %f %f\n", props[p].name, (int)props[p].flags, props[p].value.v4.x, props[p].value.v4.y,
props[p].value.v4.z, props[p].value.v4.w);
break;
case GUI_PROP_RECT: fprintf(f, "r %s %i %i %i %i %i\n", props[p].name, (int)props[p].flags, (int)props[p].value.vrect.x, (int)props[p].value.vrect.y,
(int)props[p].value.vrect.width, (int)props[p].value.vrect.height);
break;
case GUI_PROP_COLOR: fprintf(f, "c %s %i %i %i %i %i\n", props[p].name, (int)props[p].flags, props[p].value.vcolor.r, props[p].value.vcolor.g,
props[p].value.vcolor.b, props[p].value.vcolor.a);
break;
}
}
fclose(f);
return true;
}
#endif // GUI_PROPERTY_LIST_IMPLEMENTATION

View File

@ -0,0 +1,90 @@
/*******************************************************************************************
*
* raygui - a custom property list control
*
* DEPENDENCIES:
* raylib 3.0
* raygui 2.7
*
* COMPILATION (Windows - MinGW):
* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2020 Vlad Adrian (@Demizdor - https://github.com/Demizdor)
*
**********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#define RAYGUI_SUPPORT_ICONS
#include "../../src/raygui.h"
#undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
#define GUI_PROPERTY_LIST_IMPLEMENTATION
#include "dm_property_list.h"
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 450
#define SIZEOF(A) (sizeof(A)/sizeof(A[0]))
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main()
{
// Initialization
//---------------------------------------------------------------------------------------
GuiDMProperty prop[] = {
PBOOL("Bool", 0, true),
PSECTION("#102#SECTION", 0, 2),
PINT("Int", 0, 123),
PFLOAT("Float", 0, 0.99f),
PTEXT("Text", 0, (char*)&(char[30]){"Hello!"}, 30),
PSELECT("Select", 0, "ONE;TWO;THREE;FOUR", 0),
PINT_RANGE("Int Range", 0, 32, 1, 0, 100),
PRECT("Rect", 0, 0, 0, 100, 200),
PVEC2("Vec2", 0, 20, 20),
PVEC3("Vec3", 0, 12, 13, 14),
PVEC4("Vec4", 0, 12, 13, 14, 15),
PCOLOR("Color", 0, 0, 255, 0, 255),
};
int focus = 0, scroll = 0; // needed by GuiDMPropertyList()
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "raygui - property list");
SetTargetFPS(60);
GuiLoadStyleDefault();
// adjust the default raygui style a bit
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
GuiGrid((Rectangle){0,0,SCREEN_WIDTH,SCREEN_HEIGHT},20.0f, 2); // draw a fancy grid
GuiDMPropertyList((Rectangle){(SCREEN_WIDTH - 180)/2, (SCREEN_HEIGHT - 280)/2, 180, 280}, prop, SIZEOF(prop), &focus, &scroll);
if(prop[0].value.vbool)
DrawText(TextFormat("FOCUS:%i | SCROLL:%i | FPS:%i", focus, scroll, GetFPS()), prop[8].value.v2.x, prop[8].value.v2.y, 20, prop[11].value.vcolor);
EndDrawing();
//----------------------------------------------------------------------------------
}
GuiDMSaveProperties("test.props", prop, SIZEOF(prop)); // Save properties to `test.props` file at exit
CloseWindow(); // Close window and OpenGL context
return 0;
}

View File

@ -78,8 +78,8 @@ int main()
showContentArea = GuiCheckBox((Rectangle){ 565, 80, 20, 20 }, "SHOW CONTENT AREA", showContentArea); showContentArea = GuiCheckBox((Rectangle){ 565, 80, 20, 20 }, "SHOW CONTENT AREA", showContentArea);
panelContentRec.width = GuiSliderBar((Rectangle){ 590, 385, 145, 15}, "WIDTH", panelContentRec.width, 1, 600, true); panelContentRec.width = GuiSliderBar((Rectangle){ 590, 385, 145, 15}, "WIDTH", TextFormat("%i", (int)panelContentRec.width), 1, 600, true);
panelContentRec.height = GuiSliderBar((Rectangle){ 590, 410, 145, 15 }, "HEIGHT", panelContentRec.height, 1, 400, true); panelContentRec.height = GuiSliderBar((Rectangle){ 590, 410, 145, 15 }, "HEIGHT", TextFormat("%i", (int)panelContentRec.height), 1, 400, true);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -102,31 +102,31 @@ static void DrawStyleEditControls(void)
int style = GuiGetStyle(SCROLLBAR, BORDER_WIDTH); int style = GuiGetStyle(SCROLLBAR, BORDER_WIDTH);
GuiLabel((Rectangle){ 555, 195, 110, 10 }, "BORDER_WIDTH"); GuiLabel((Rectangle){ 555, 195, 110, 10 }, "BORDER_WIDTH");
GuiSpinner((Rectangle){ 670, 190, 90, 20 }, &style, 0, 6, false); GuiSpinner((Rectangle){ 670, 190, 90, 20 }, NULL, &style, 0, 6, false);
GuiSetStyle(SCROLLBAR, BORDER_WIDTH, style); GuiSetStyle(SCROLLBAR, BORDER_WIDTH, style);
style = GuiGetStyle(SCROLLBAR, ARROWS_SIZE); style = GuiGetStyle(SCROLLBAR, ARROWS_SIZE);
GuiLabel((Rectangle){ 555, 220, 110, 10 }, "ARROWS_SIZE"); GuiLabel((Rectangle){ 555, 220, 110, 10 }, "ARROWS_SIZE");
GuiSpinner((Rectangle){ 670, 215, 90, 20 }, &style, 4, 14, false); GuiSpinner((Rectangle){ 670, 215, 90, 20 }, NULL, &style, 4, 14, false);
GuiSetStyle(SCROLLBAR, ARROWS_SIZE, style); GuiSetStyle(SCROLLBAR, ARROWS_SIZE, style);
style = GuiGetStyle(SCROLLBAR, INNER_PADDING); style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
GuiLabel((Rectangle){ 555, 245, 110, 10 }, "INNER_PADDING"); GuiLabel((Rectangle){ 555, 245, 110, 10 }, "SLIDER_PADDING");
GuiSpinner((Rectangle){ 670, 240, 90, 20 }, &style, 0, 14, false); GuiSpinner((Rectangle){ 670, 240, 90, 20 }, NULL, &style, 0, 14, false);
GuiSetStyle(SCROLLBAR, INNER_PADDING, style); GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
style = GuiCheckBox((Rectangle){ 565, 280, 20, 20 }, "ARROWS_VISIBLE", GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)); style = GuiCheckBox((Rectangle){ 565, 280, 20, 20 }, "ARROWS_VISIBLE", GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE));
GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, style); GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, style);
style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING); style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
GuiLabel((Rectangle){ 555, 325, 110, 10 }, "SLIDER_PADDING"); GuiLabel((Rectangle){ 555, 325, 110, 10 }, "SLIDER_PADDING");
GuiSpinner((Rectangle){ 670, 320, 90, 20 }, &style, 0, 14, false); GuiSpinner((Rectangle){ 670, 320, 90, 20 }, NULL, &style, 0, 14, false);
GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style); GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
style = GuiGetStyle(SCROLLBAR, SLIDER_SIZE); style = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH);
GuiLabel((Rectangle){ 555, 350, 110, 10 }, "SLIDER_SIZE"); GuiLabel((Rectangle){ 555, 350, 110, 10 }, "SLIDER_WIDTH");
GuiSpinner((Rectangle){ 670, 345, 90, 20 }, &style, 2, 100, false); GuiSpinner((Rectangle){ 670, 345, 90, 20 }, NULL, &style, 2, 100, false);
GuiSetStyle(SCROLLBAR, SLIDER_SIZE, style); GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, style);
const char *text = GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE? "SCROLLBAR: LEFT" : "SCROLLBAR: RIGHT"; const char *text = GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE? "SCROLLBAR: LEFT" : "SCROLLBAR: RIGHT";
style = GuiToggle((Rectangle){ 560, 110, 200, 35 }, text, GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE)); style = GuiToggle((Rectangle){ 560, 110, 200, 35 }, text, GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE));
@ -139,12 +139,12 @@ static void DrawStyleEditControls(void)
style = GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); style = GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
GuiLabel((Rectangle){ 555, 35, 110, 10 }, "SCROLLBAR_WIDTH"); GuiLabel((Rectangle){ 555, 35, 110, 10 }, "SCROLLBAR_WIDTH");
GuiSpinner((Rectangle){ 670, 30, 90, 20 }, &style, 6, 30, false); GuiSpinner((Rectangle){ 670, 30, 90, 20 }, NULL, &style, 6, 30, false);
GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, style); GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, style);
style = GuiGetStyle(DEFAULT, BORDER_WIDTH); style = GuiGetStyle(DEFAULT, BORDER_WIDTH);
GuiLabel((Rectangle){ 555, 60, 110, 10 }, "BORDER_WIDTH"); GuiLabel((Rectangle){ 555, 60, 110, 10 }, "BORDER_WIDTH");
GuiSpinner((Rectangle){ 670, 55, 90, 20 }, &style, 0, 20, false); GuiSpinner((Rectangle){ 670, 55, 90, 20 }, NULL, &style, 0, 20, false);
GuiSetStyle(DEFAULT, BORDER_WIDTH, style); GuiSetStyle(DEFAULT, BORDER_WIDTH, style);
//---------------------------------------------------------- //----------------------------------------------------------
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,70 @@
cmake_minimum_required(VERSION 3.11)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
project(raygui C)
# Config options
option(BUILD_RAYGUI_EXAMPLES "Build the examples." ON)
# Directory Variables
set(RAYGUI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
set(RAYGUI_SRC ${RAYGUI_ROOT}/src)
set(RAYGUI_EXAMPLES ${RAYGUI_ROOT}/examples)
# raygui
add_library(raygui INTERFACE)
file(GLOB sources ${RAYGUI_SRC}/*.h)
set(RAYGUI_HEADERS ${sources})
install(FILES
${RAYGUI_HEADERS} DESTINATION include
)
target_include_directories(raygui INTERFACE ${RAYGUI_SRC})
# Examples
if(${BUILD_RAYGUI_EXAMPLES})
find_package(Raylib)
# Get the sources together
set(example_dirs
custom_file_dialog
image_raw_importer
portable_window
scroll_panel
text_box_selection
controls_test_suite
image_exporter
property_list
text_editor
)
set(example_sources)
set(example_resources)
foreach(example_dir ${example_dirs})
# Get the .c files
file(GLOB sources ${RAYGUI_EXAMPLES}/${example_dir}/*.c)
list(APPEND example_sources ${sources})
# Any any resources
file(GLOB resources ${RAYGUI_EXAMPLES}/${example_dir}/resources/*)
list(APPEND example_resources ${resources})
endforeach()
# Do each example
foreach(example_source ${example_sources})
# Create the basename for the example
get_filename_component(example_name ${example_source} NAME)
string(REPLACE ".c" "${OUTPUT_EXT}" example_name ${example_name})
# Setup the example
add_executable(${example_name} ${example_source})
target_link_libraries(${example_name} PUBLIC raylib raygui)
string(REGEX MATCH ".*/.*/" resources_dir ${example_source})
string(APPEND resources_dir "resources")
endforeach()
# Copy all of the resource files to the destination
file(COPY ${example_resources} DESTINATION "resources/")
endif()

13
projects/CMake/README.md Normal file
View File

@ -0,0 +1,13 @@
# raygui CMake Definitions
This provides CMake definition files for raygui.
## Usage
```
cd projects/CMake
mkdir build
cd build
cmake ..
make
```

View File

@ -0,0 +1,17 @@
find_package(raylib 3.0.0 QUIET CONFIG)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG df5c522049ddd82fba048a6bd069338999729d6a
)
FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED) # Have we downloaded raylib yet?
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(raylib)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # or games
add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
endif()
endif()

View File

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

View File

@ -0,0 +1,55 @@

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

View File

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

1074
src/gui_textbox_extended.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,35 +2,9 @@
* *
* rIcons - Icons pack intended for tools development with raygui * rIcons - Icons pack intended for tools development with raygui
* *
* CONFIGURATION:
*
* #define RICONS_IMPLEMENTATION
* Generates the implementation of the library into the included file.
* If not defined, the library is in header only mode and can be included in other headers
* or source files without problems. But only ONE file should hold the implementation.
*
* #define RICONS_STANDALONE
* Avoid raylib.h header inclusion in this file. Icon drawing function must be provided by
* the user (check library implementation for further details).
*
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2019 Ramon Santamaria (@raysan5) * Copyright (c) 2019-2020 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
@ -40,234 +14,288 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define RICONS_COUNT 199 // Number of icons included #define RICON_MAX_ICONS 256 // Maximum number of icons
#define RICONS_SIZE 16 // Size of icons (squared) #define RICON_SIZE 16 // Size of icons (squared)
#define RICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
// Icons data is defined by bit array (every bit represents one pixel)
// Those arrays are stored as unsigned int data arrays, so every array
// element defines 32 pixels (bits) of information
// Number of elemens depend on RICON_SIZE (by default 16x16 pixels)
#define RICON_DATA_ELEMENTS (RICON_SIZE*RICON_SIZE/32)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Icons enumeration // Icons enumeration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef enum { typedef enum {
RICON_NONE = 0, RICON_NONE = 0,
RICON_FOLDER_FILE_OPEN, RICON_FOLDER_FILE_OPEN = 1,
RICON_FILE_SAVE_CLASSIC, RICON_FILE_SAVE_CLASSIC = 2,
RICON_FOLDER_OPEN, RICON_FOLDER_OPEN = 3,
RICON_FOLDER_SAVE, RICON_FOLDER_SAVE = 4,
RICON_FILE_OPEN, RICON_FILE_OPEN = 5,
RICON_FILE_SAVE, RICON_FILE_SAVE = 6,
RICON_FILE_EXPORT, RICON_FILE_EXPORT = 7,
RICON_FILE_NEW, RICON_FILE_NEW = 8,
RICON_FILE_DELETE, RICON_FILE_DELETE = 9,
RICON_FILETYPE_TEXT, RICON_FILETYPE_TEXT = 10,
RICON_FILETYPE_AUDIO, RICON_FILETYPE_AUDIO = 11,
RICON_FILETYPE_IMAGE, RICON_FILETYPE_IMAGE = 12,
RICON_FILETYPE_PLAY, RICON_FILETYPE_PLAY = 13,
RICON_FILETYPE_VIDEO, RICON_FILETYPE_VIDEO = 14,
RICON_FILETYPE_INFO, RICON_FILETYPE_INFO = 15,
RICON_FILE_COPY, RICON_FILE_COPY = 16,
RICON_FILE_CUT, RICON_FILE_CUT = 17,
RICON_FILE_PASTE, RICON_FILE_PASTE = 18,
RICON_CURSOR_HAND, RICON_CURSOR_HAND = 19,
RICON_CURSOR_POINTER, RICON_CURSOR_POINTER = 20,
RICON_CURSOR_CLASSIC, RICON_CURSOR_CLASSIC = 21,
RICON_PENCIL, RICON_PENCIL = 22,
RICON_PENCIL_BIG, RICON_PENCIL_BIG = 23,
RICON_BRUSH_CLASSIC, RICON_BRUSH_CLASSIC = 24,
RICON_BRUSH_PAINTER, RICON_BRUSH_PAINTER = 25,
RICON_WATER_DROP, RICON_WATER_DROP = 26,
RICON_COLOR_PICKER, RICON_COLOR_PICKER = 27,
RICON_RUBBER, RICON_RUBBER = 28,
RICON_COLOR_BUCKET, RICON_COLOR_BUCKET = 29,
RICON_TEXT_T, RICON_TEXT_T = 30,
RICON_TEXT_A, RICON_TEXT_A = 31,
RICON_SCALE, RICON_SCALE = 32,
RICON_RESIZE, RICON_RESIZE = 33,
RICON_FILTER_POINT, RICON_FILTER_POINT = 34,
RICON_FILTER_BILINEAR, RICON_FILTER_BILINEAR = 35,
RICON_CROP, RICON_CROP = 36,
RICON_CROP_ALPHA, RICON_CROP_ALPHA = 37,
RICON_SQUARE_TOGGLE, RICON_SQUARE_TOGGLE = 38,
RICON_SIMMETRY, RICON_SYMMETRY = 39,
RICON_SIMMETRY_HORIZONTAL, RICON_SYMMETRY_HORIZONTAL = 40,
RICON_SIMMETRY_VERTICAL, RICON_SYMMETRY_VERTICAL = 41,
RICON_LENS, RICON_LENS = 42,
RICON_LENS_BIG, RICON_LENS_BIG = 43,
RICON_EYE_ON, RICON_EYE_ON = 44,
RICON_EYE_OFF, RICON_EYE_OFF = 45,
RICON_FILTER_TOP, RICON_FILTER_TOP = 46,
RICON_FILTER, RICON_FILTER = 47,
RICON_TARGET_POINT, RICON_TARGET_POINT = 48,
RICON_TARGET_SMALL, RICON_TARGET_SMALL = 49,
RICON_TARGET_BIG, RICON_TARGET_BIG = 50,
RICON_TARGET_MOVE, RICON_TARGET_MOVE = 51,
RICON_CURSOR_MOVE, RICON_CURSOR_MOVE = 52,
RICON_CURSOR_SCALE, RICON_CURSOR_SCALE = 53,
RICON_CURSOR_SCALE_RIGHT, RICON_CURSOR_SCALE_RIGHT = 54,
RICON_CURSOR_SCALE_LEFT, RICON_CURSOR_SCALE_LEFT = 55,
RICON_UNDO, RICON_UNDO = 56,
RICON_REDO, RICON_REDO = 57,
RICON_REREDO, RICON_REREDO = 58,
RICON_MUTATE, RICON_MUTATE = 59,
RICON_ROTATE, RICON_ROTATE = 60,
RICON_REPEAT, RICON_REPEAT = 61,
RICON_SHUFFLE, RICON_SHUFFLE = 62,
RICON_EMPTYBOX, RICON_EMPTYBOX = 63,
RICON_TARGET, RICON_TARGET = 64,
RICON_TARGET_SMALL_FILL, RICON_TARGET_SMALL_FILL = 65,
RICON_TARGET_BIG_FILL, RICON_TARGET_BIG_FILL = 66,
RICON_TARGET_MOVE_FILL, RICON_TARGET_MOVE_FILL = 67,
RICON_CURSOR_MOVE_FILL, RICON_CURSOR_MOVE_FILL = 68,
RICON_CURSOR_SCALE_FILL, RICON_CURSOR_SCALE_FILL = 69,
RICON_CURSOR_SCALE_RIGHT_FILL, RICON_CURSOR_SCALE_RIGHT_FILL = 70,
RICON_CURSOR_SCALE_LEFT_FILL, RICON_CURSOR_SCALE_LEFT_FILL = 71,
RICON_UNDO_FILL, RICON_UNDO_FILL = 72,
RICON_REDO_FILL, RICON_REDO_FILL = 73,
RICON_REREDO_FILL, RICON_REREDO_FILL = 74,
RICON_MUTATE_FILL, RICON_MUTATE_FILL = 75,
RICON_ROTATE_FILL, RICON_ROTATE_FILL = 76,
RICON_REPEAT_FILL, RICON_REPEAT_FILL = 77,
RICON_SHUFFLE_FILL, RICON_SHUFFLE_FILL = 78,
RICON_EMPTYBOX_SMALL, RICON_EMPTYBOX_SMALL = 79,
RICON_BOX, RICON_BOX = 80,
RICON_BOX_TOP, RICON_BOX_TOP = 81,
RICON_BOX_TOP_RIGHT, RICON_BOX_TOP_RIGHT = 82,
RICON_BOX_RIGHT, RICON_BOX_RIGHT = 83,
RICON_BOX_BOTTOM_RIGHT, RICON_BOX_BOTTOM_RIGHT = 84,
RICON_BOX_BOTTOM, RICON_BOX_BOTTOM = 85,
RICON_BOX_BOTTOM_LEFT, RICON_BOX_BOTTOM_LEFT = 86,
RICON_BOX_LEFT, RICON_BOX_LEFT = 87,
RICON_BOX_TOP_LEFT, RICON_BOX_TOP_LEFT = 88,
RICON_BOX_CENTER, RICON_BOX_CENTER = 89,
RICON_BOX_CIRCLE_MASK, RICON_BOX_CIRCLE_MASK = 90,
RICON_POT, RICON_POT = 91,
RICON_ALPHA_MULTIPLY, RICON_ALPHA_MULTIPLY = 92,
RICON_ALPHA_CLEAR, RICON_ALPHA_CLEAR = 93,
RICON_DITHERING, RICON_DITHERING = 94,
RICON_MIPMAPS, RICON_MIPMAPS = 95,
RICON_BOX_GRID, RICON_BOX_GRID = 96,
RICON_GRID, RICON_GRID = 97,
RICON_BOX_CORNERS_SMALL, RICON_BOX_CORNERS_SMALL = 98,
RICON_BOX_CORNERS_BIG, RICON_BOX_CORNERS_BIG = 99,
RICON_FOUR_BOXES, RICON_FOUR_BOXES = 100,
RICON_GRID_FILL, RICON_GRID_FILL = 101,
RICON_BOX_MULTISIZE, RICON_BOX_MULTISIZE = 102,
RICON_ZOOM_SMALL, RICON_ZOOM_SMALL = 103,
RICON_ZOOM_MEDIUM, RICON_ZOOM_MEDIUM = 104,
RICON_ZOOM_BIG, RICON_ZOOM_BIG = 105,
RICON_ZOOM_ALL, RICON_ZOOM_ALL = 106,
RICON_ZOOM_CENTER, RICON_ZOOM_CENTER = 107,
RICON_BOX_DOTS_SMALL, RICON_BOX_DOTS_SMALL = 108,
RICON_BOX_DOTS_BIG, RICON_BOX_DOTS_BIG = 109,
RICON_BOX_CONCENTRIC, RICON_BOX_CONCENTRIC = 110,
RICON_BOX_GRID_BIG, RICON_BOX_GRID_BIG = 111,
RICON_OK_TICK, RICON_OK_TICK = 112,
RICON_CROSS, RICON_CROSS = 113,
RICON_ARROW_LEFT, RICON_ARROW_LEFT = 114,
RICON_ARROW_RIGHT, RICON_ARROW_RIGHT = 115,
RICON_ARROW_BOTTOM, RICON_ARROW_BOTTOM = 116,
RICON_ARROW_TOP, RICON_ARROW_TOP = 117,
RICON_ARROW_LEFT_FILL, RICON_ARROW_LEFT_FILL = 118,
RICON_ARROW_RIGHT_FILL, RICON_ARROW_RIGHT_FILL = 119,
RICON_ARROW_BOTTOM_FILL, RICON_ARROW_BOTTOM_FILL = 120,
RICON_ARROW_TOP_FILL, RICON_ARROW_TOP_FILL = 121,
RICON_AUDIO, RICON_AUDIO = 122,
RICON_FX, RICON_FX = 123,
RICON_WAVE, RICON_WAVE = 124,
RICON_WAVE_SINUS, RICON_WAVE_SINUS = 125,
RICON_WAVE_SQUARE, RICON_WAVE_SQUARE = 126,
RICON_WAVE_TRIANGULAR, RICON_WAVE_TRIANGULAR = 127,
RICON_CROSS_SMALL, RICON_CROSS_SMALL = 128,
RICON_PLAYER_PREVIOUS, RICON_PLAYER_PREVIOUS = 129,
RICON_PLAYER_PLAY_BACK, RICON_PLAYER_PLAY_BACK = 130,
RICON_PLAYER_PLAY, RICON_PLAYER_PLAY = 131,
RICON_PLAYER_PAUSE, RICON_PLAYER_PAUSE = 132,
RICON_PLAYER_STOP, RICON_PLAYER_STOP = 133,
RICON_PLAYER_NEXT, RICON_PLAYER_NEXT = 134,
RICON_PLAYER_RECORD, RICON_PLAYER_RECORD = 135,
RICON_MAGNET, RICON_MAGNET = 136,
RICON_LOCK_CLOSE, RICON_LOCK_CLOSE = 137,
RICON_LOCK_OPEN, RICON_LOCK_OPEN = 138,
RICON_CLOCK, RICON_CLOCK = 139,
RICON_TOOLS, RICON_TOOLS = 140,
RICON_GEAR, RICON_GEAR = 141,
RICON_GEAR_BIG, RICON_GEAR_BIG = 142,
RICON_BIN, RICON_BIN = 143,
RICON_HAND_POINTER, RICON_HAND_POINTER = 144,
RICON_LASER, RICON_LASER = 145,
RICON_COIN, RICON_COIN = 146,
RICON_EXPLOSION, RICON_EXPLOSION = 147,
RICON_1UP, RICON_1UP = 148,
RICON_PLAYER, RICON_PLAYER = 149,
RICON_PLAYER_JUMP, RICON_PLAYER_JUMP = 150,
RICON_KEY, RICON_KEY = 151,
RICON_DEMON, RICON_DEMON = 152,
RICON_TEXT_POPUP, RICON_TEXT_POPUP = 153,
RICON_GEAR_EX, RICON_GEAR_EX = 154,
RICON_CRACK, RICON_CRACK = 155,
RICON_CRACK_POINTS, RICON_CRACK_POINTS = 156,
RICON_STAR, RICON_STAR = 157,
RICON_DOOR, RICON_DOOR = 158,
RICON_EXIT, RICON_EXIT = 159,
RICON_MODE_2D, RICON_MODE_2D = 160,
RICON_MODE_3D, RICON_MODE_3D = 161,
RICON_CUBE, RICON_CUBE = 162,
RICON_CUBE_FACE_TOP, RICON_CUBE_FACE_TOP = 163,
RICON_CUBE_FACE_LEFT, RICON_CUBE_FACE_LEFT = 164,
RICON_CUBE_FACE_FRONT, RICON_CUBE_FACE_FRONT = 165,
RICON_CUBE_FACE_BOTTOM, RICON_CUBE_FACE_BOTTOM = 166,
RICON_CUBE_FACE_RIGHT, RICON_CUBE_FACE_RIGHT = 167,
RICON_CUBE_FACE_BACK, RICON_CUBE_FACE_BACK = 168,
RICON_CAMERA, RICON_CAMERA = 169,
RICON_SPECIAL, RICON_SPECIAL = 170,
RICON_LINK_NET, RICON_LINK_NET = 171,
RICON_LINK_BOXES, RICON_LINK_BOXES = 172,
RICON_LINK_MULTI, RICON_LINK_MULTI = 173,
RICON_LINK, RICON_LINK = 174,
RICON_LINK_BROKE, RICON_LINK_BROKE = 175,
RICON_TEXT_NOTES, RICON_TEXT_NOTES = 176,
RICON_NOTEBOOK, RICON_NOTEBOOK = 177,
RICON_SUITCASE, RICON_SUITCASE = 178,
RICON_SUITCASE_ZIP, RICON_SUITCASE_ZIP = 179,
RICON_MAILBOX, RICON_MAILBOX = 180,
RICON_MONITOR, RICON_MONITOR = 181,
RICON_PRINTER, RICON_PRINTER = 182,
RICON_PHOTO_CAMERA, RICON_PHOTO_CAMERA = 183,
RICON_PHOTO_CAMERA_FLASH, RICON_PHOTO_CAMERA_FLASH = 184,
RICON_HOUSE, RICON_HOUSE = 185,
RICON_HEART, RICON_HEART = 186,
RICON_CORNER, RICON_CORNER = 187,
RICON_VERTICAL_BARS, RICON_VERTICAL_BARS = 188,
RICON_VERTICAL_BARS_FILL, RICON_VERTICAL_BARS_FILL = 189,
RICON_LIFE_BARS, RICON_LIFE_BARS = 190,
RICON_INFO, RICON_INFO = 191,
RICON_CROSSLINE, RICON_CROSSLINE = 192,
RICON_HELP, RICON_HELP = 193,
RICON_FILETYPE_ALPHA, RICON_FILETYPE_ALPHA = 194,
RICON_FILETYPE_HOME, RICON_FILETYPE_HOME = 195,
RICON_LAYERS_VISIBLE, RICON_LAYERS_VISIBLE = 196,
RICON_LAYERS, RICON_LAYERS = 197,
RICON_WINDOW RICON_WINDOW = 198,
} rIconDescription; RICON_HIDPI = 199,
RICON_200 = 200,
RICON_201 = 201,
RICON_202 = 202,
RICON_203 = 203,
RICON_204 = 204,
RICON_205 = 205,
RICON_206 = 206,
RICON_207 = 207,
RICON_208 = 208,
RICON_209 = 209,
RICON_210 = 210,
RICON_211 = 211,
RICON_212 = 212,
RICON_213 = 213,
RICON_214 = 214,
RICON_215 = 215,
RICON_216 = 216,
RICON_217 = 217,
RICON_218 = 218,
RICON_219 = 219,
RICON_220 = 220,
RICON_221 = 221,
RICON_222 = 222,
RICON_223 = 223,
RICON_224 = 224,
RICON_225 = 225,
RICON_226 = 226,
RICON_227 = 227,
RICON_228 = 228,
RICON_229 = 229,
RICON_230 = 230,
RICON_231 = 231,
RICON_232 = 232,
RICON_233 = 233,
RICON_234 = 234,
RICON_235 = 235,
RICON_236 = 236,
RICON_237 = 237,
RICON_238 = 238,
RICON_239 = 239,
RICON_240 = 240,
RICON_241 = 241,
RICON_242 = 242,
RICON_243 = 243,
RICON_244 = 244,
RICON_245 = 245,
RICON_246 = 246,
RICON_247 = 247,
RICON_248 = 248,
RICON_249 = 249,
RICON_250 = 250,
RICON_251 = 251,
RICON_252 = 252,
RICON_253 = 253,
RICON_254 = 254,
RICON_255 = 255,
} guiIconName;
//---------------------------------------------------------------------------------- #endif // RICONS_H
// Module Functions Declaration
//----------------------------------------------------------------------------------
void DrawIcon(int iconId, Vector2 position, int pixelSize, Color color);
#endif // RICONS_H
/***********************************************************************************
*
* RICONS IMPLEMENTATION
*
************************************************************************************/
#if defined(RICONS_IMPLEMENTATION) #if defined(RICONS_IMPLEMENTATION)
//----------------------------------------------------------------------------------
#if !defined(RICONS_STANDALONE) // Icons data (allocated on memory data section by default)
#include "raylib.h" // Required for: Icons drawing function: DrawRectangle() // NOTE: A new icon set could be loaded over this array using GuiLoadIcons(),
#endif // just note that loaded icons set must be same RICON_SIZE
//----------------------------------------------------------------------------------
static const unsigned int RICONS[RICONS_COUNT*8] = { static unsigned int guiIcons[RICON_MAX_ICONS*RICON_DATA_ELEMENTS] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_NONE 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_NONE
0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // RICON_FOLDER_FILE_OPEN 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // RICON_FOLDER_FILE_OPEN
0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // RICON_FILE_SAVE_CLASSIC 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // RICON_FILE_SAVE_CLASSIC
@ -467,27 +495,62 @@ static const unsigned int RICONS[RICONS_COUNT*8] = {
0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS_VISIBLE 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS_VISIBLE
0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS
0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // RICON_WINDOW 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // RICON_WINDOW
0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // RICON_HIDPI
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_200
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_201
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_202
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_203
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_204
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_205
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_206
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_207
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_208
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_209
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_210
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_211
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_212
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_213
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_214
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_215
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_216
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_217
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_218
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_219
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_220
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_221
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_222
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_223
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_224
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_225
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_226
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_227
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_228
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_229
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_230
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_231
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_232
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_233
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_234
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_235
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_236
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_237
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_238
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_239
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_240
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_241
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_242
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_243
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_244
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_245
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_246
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_247
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_248
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_249
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_250
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_251
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_252
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_253
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_254
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_255
}; };
// Draw selected icon using rectangles pixel-by-pixel
void DrawIcon(int iconId, Vector2 position, int pixelSize, Color color)
{
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
for (int i = 0, y = 0; i < RICONS_SIZE*RICONS_SIZE/32; i++)
{
for (int k = 0; k < 32; k++)
{
if (BIT_CHECK(RICONS[8*iconId + i], k))
{
#if !defined(RICONS_STANDALONE)
DrawRectangle(position.x + (k%RICONS_SIZE)*pixelSize, position.y + y*pixelSize, pixelSize, pixelSize, color);
#endif
}
if ((k == 15) || (k == 31)) y++;
}
}
}
#endif // RICONS_IMPLEMENTATION #endif // RICONS_IMPLEMENTATION

View File

@ -19,6 +19,6 @@ p 00 09 0x94795dff DEFAULT_BORDER_COLOR_DISABLED
p 00 10 0xc2a37aff DEFAULT_BASE_COLOR_DISABLED p 00 10 0xc2a37aff DEFAULT_BASE_COLOR_DISABLED
p 00 11 0x9c8369ff DEFAULT_TEXT_COLOR_DISABLED p 00 11 0x9c8369ff DEFAULT_TEXT_COLOR_DISABLED
p 00 16 0x0000000f TEXT_SIZE p 00 16 0x0000000f TEXT_SIZE
p 00 17 0x00000000 TEXT_SPACING p 00 17 0x00000001 TEXT_SPACING
p 00 18 0xd77575ff DEFAULT_LINE_COLOR p 00 18 0xd77575ff DEFAULT_LINE_COLOR
p 00 19 0xfff5e1ff DEFAULT_BACKGROUND_COLOR p 00 19 0xfff5e1ff DEFAULT_BACKGROUND_COLOR

View File

@ -8,7 +8,7 @@
f 14 0 Kyrou 7 Wide.ttf f 14 0 Kyrou 7 Wide.ttf
p 00 00 0x2f7486ff DEFAULT_BORDER_COLOR_NORMAL p 00 00 0x2f7486ff DEFAULT_BORDER_COLOR_NORMAL
p 00 01 0x024658ff DEFAULT_BASE_COLOR_NORMAL p 00 01 0x024658ff DEFAULT_BASE_COLOR_NORMAL
p 00 02 0x2489a2ff DEFAULT_TEXT_COLOR_NORMAL p 00 02 0x51bfd3ff DEFAULT_TEXT_COLOR_NORMAL
p 00 03 0x82cde0ff DEFAULT_BORDER_COLOR_FOCUSED p 00 03 0x82cde0ff DEFAULT_BORDER_COLOR_FOCUSED
p 00 04 0x3299b4ff DEFAULT_BASE_COLOR_FOCUSED p 00 04 0x3299b4ff DEFAULT_BASE_COLOR_FOCUSED
p 00 05 0xb6e1eaff DEFAULT_TEXT_COLOR_FOCUSED p 00 05 0xb6e1eaff DEFAULT_TEXT_COLOR_FOCUSED
@ -18,7 +18,7 @@ p 00 08 0xd86f36ff DEFAULT_TEXT_COLOR_PRESSED
p 00 09 0x134b5aff DEFAULT_BORDER_COLOR_DISABLED p 00 09 0x134b5aff DEFAULT_BORDER_COLOR_DISABLED
p 00 10 0x02313dff DEFAULT_BASE_COLOR_DISABLED p 00 10 0x02313dff DEFAULT_BASE_COLOR_DISABLED
p 00 11 0x17505fff DEFAULT_TEXT_COLOR_DISABLED p 00 11 0x17505fff DEFAULT_TEXT_COLOR_DISABLED
p 00 16 0x0000000e TEXT_SIZE p 00 16 0x0000000e DEFAULT_TEXT_SIZE
p 00 17 0x00000000 TEXT_SPACING p 00 17 0x00000000 DEFAULT_TEXT_SPACING
p 00 18 0x81c0d0ff DEFAULT_LINE_COLOR p 00 18 0x81c0d0ff DEFAULT_LINE_COLOR
p 00 19 0x00222bff DEFAULT_BACKGROUND_COLOR p 00 19 0x00222bff DEFAULT_BACKGROUND_COLOR

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB