├── .editorconfig ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── examples ├── CMakeLists.txt ├── LICENSE ├── minshell.html ├── raylib-nuklear-demo.c ├── raylib-nuklear-example.c ├── raylib-nuklear-example.png ├── raylib-nuklear-font-default.c ├── raylib-nuklear-font.c ├── raylib-nuklear-texture.c └── resources │ ├── anonymous_pro_bold.ttf │ └── test-image.png ├── include ├── CMakeLists.txt ├── nuklear.h ├── raylib-nuklear-font.h └── raylib-nuklear.h └── test ├── CMakeLists.txt ├── raylib-assert.h ├── raylib-nuklear-test.c └── resources ├── anonymous_pro_bold.ttf └── test-image.png /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .vscode 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/nuklear"] 2 | path = vendor/nuklear 3 | url = https://github.com/Immediate-Mode-UI/Nuklear.git 4 | ignore = dirty 5 | branch = master 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(raylib_nuklear 3 | DESCRIPTION "raylib_nuklear: Nuklear immediate mode GUI for raylib." 4 | HOMEPAGE_URL "https://github.com/robloach/raylib-nuklear" 5 | VERSION 5.5.0 6 | LANGUAGES C 7 | ) 8 | 9 | # raylib-nuklear 10 | add_subdirectory(include) 11 | 12 | # Options 13 | if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") 14 | set(RAYLIB_NUKLEAR_IS_MAIN TRUE) 15 | else() 16 | set(RAYLIB_NUKLEAR_IS_MAIN FALSE) 17 | endif() 18 | option(RAYLIB_NUKLEAR_BUILD_EXAMPLES "Examples" ${RAYLIB_NUKLEAR_IS_MAIN}) 19 | 20 | # Examples 21 | if (RAYLIB_NUKLEAR_BUILD_EXAMPLES) 22 | add_subdirectory(examples) 23 | 24 | # Testing 25 | include(CTest) 26 | enable_testing() 27 | if (BUILD_TESTING) 28 | # set(CTEST_CUSTOM_TESTS_IGNORE 29 | # pkg-config--static 30 | # ) 31 | # Always print verbose output when tests fail if run using `make test`. 32 | list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") 33 | add_subdirectory(test) 34 | endif() 35 | endif() 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Rob Loach (@RobLoach) 2 | 3 | This software is provided "as-is", without any express or implied warranty. In no event 4 | will the authors be held liable for any damages arising from the use of this software. 5 | 6 | Permission is granted to anyone to use this software for any purpose, including commercial 7 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | 1. The origin of this software must not be misrepresented; you must not claim that you 10 | wrote the original software. If you use this software in a product, an acknowledgment 11 | in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | as being the original software. 15 | 16 | 3. This notice may not be removed or altered from any source distribution. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raylib-nuklear 2 | 3 | Use the [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) immediate mode cross-platform GUI library in [raylib](https://www.raylib.com/). 4 | 5 | [![raylib-nuklear-example Screenshot](examples/raylib-nuklear-example.png)](examples) 6 | 7 | ## Usage 8 | 9 | 1. Since this is a header-only library, you must first define `RAYLIB_NUKLEAR_IMPLEMENTATION` in one of your `.c` files... 10 | ``` c 11 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 12 | ``` 13 | 2. Include the [`raylib-nuklear.h`](include/raylib-nuklear.h) file... 14 | ``` c 15 | #include "path/to/raylib-nuklear.h" 16 | ``` 17 | 3. Use `InitNuklear(fontSize)` or `InitNuklearEx(font, fontSize)` to create the nuklear context... 18 | ``` c 19 | struct nk_context *ctx = InitNuklear(10); 20 | ``` 21 | 4. Build your Nuklear GUI through the standard [Nuklear API](https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window) 22 | 5. Update the input for the GUI using `UpdateNuklear(ctx)` 23 | 6. Render the context using `DrawNuklear(ctx)` 24 | 7. Destroy the nuklear context with `UnloadNuklear(ctx)` 25 | 26 | ## Example 27 | 28 | ``` c 29 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 30 | #include "raylib-nuklear.h" 31 | 32 | int main() { 33 | InitWindow(640, 480, "raylib-nuklear example"); 34 | 35 | // Create the Nuklear Context 36 | int fontSize = 10; 37 | struct nk_context *ctx = InitNuklear(fontSize); 38 | 39 | while (!WindowShouldClose()) { 40 | // Update the Nuklear context, along with input 41 | UpdateNuklear(ctx); 42 | 43 | // Nuklear GUI Code 44 | // https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window 45 | if (nk_begin(ctx, "Nuklear", nk_rect(100, 100, 220, 220), 46 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { 47 | nk_layout_row_static(ctx, 50, 150, 1); 48 | if (nk_button_label(ctx, "Button")) { 49 | // Button was clicked! 50 | } 51 | } 52 | nk_end(ctx); 53 | 54 | // Render 55 | BeginDrawing(); 56 | ClearBackground(RAYWHITE); 57 | 58 | // Render the Nuklear GUI 59 | DrawNuklear(ctx); 60 | 61 | EndDrawing(); 62 | } 63 | 64 | // De-initialize the Nuklear GUI 65 | UnloadNuklear(ctx); 66 | 67 | CloseWindow(); 68 | return 0; 69 | } 70 | ``` 71 | 72 | ## API 73 | 74 | ``` c 75 | struct nk_context* InitNuklear(int fontSize); // Initialize the Nuklear GUI context using raylib's font 76 | struct nk_context* InitNuklearEx(Font font, float fontSize); // Initialize the Nuklear GUI context, with a custom font 77 | Font LoadFontFromNuklear(int fontSize); // Loads the default Nuklear font 78 | void UpdateNuklear(struct nk_context * ctx); // Update the input state and internal components for Nuklear 79 | void UpdateNuklearEx(struct nk_context * ctx, float deltaTime); // Update the input state and internal components for Nuklear, with a custom frame time 80 | void DrawNuklear(struct nk_context * ctx); // Render the Nuklear GUI on the screen 81 | void UnloadNuklear(struct nk_context * ctx); // Deinitialize the Nuklear context 82 | struct nk_color ColorToNuklear(Color color); // Convert a raylib Color to a Nuklear color object 83 | struct nk_colorf ColorToNuklearF(Color color); // Convert a raylib Color to a Nuklear floating color 84 | struct Color ColorFromNuklear(struct nk_color color); // Convert a Nuklear color to a raylib Color 85 | struct Color ColorFromNuklearF(struct nk_colorf color); // Convert a Nuklear floating color to a raylib Color 86 | struct Rectangle RectangleFromNuklear(struct nk_context * ctx, struct nk_rect rect); // Convert a Nuklear rectangle to a raylib Rectangle 87 | struct nk_rect RectangleToNuklear(struct nk_context * ctx, Rectangle rect); // Convert a raylib Rectangle to a Nuklear Rectangle 88 | struct nk_image TextureToNuklear(Texture tex); // Convert a raylib Texture to A Nuklear image 89 | struct Texture TextureFromNuklear(struct nk_image img); // Convert a Nuklear image to a raylib Texture 90 | struct nk_image LoadNuklearImage(const char* path); // Load a Nuklear image 91 | void UnloadNuklearImage(struct nk_image img); // Unload a Nuklear image. And free its data 92 | void CleanupNuklearImage(struct nk_image img); // Frees the data stored by the Nuklear image 93 | void SetNuklearScaling(struct nk_context * ctx, float scaling); // Sets the scaling for the given Nuklear context 94 | float GetNuklearScaling(struct nk_context * ctx); // Retrieves the scaling of the given Nuklear context 95 | ``` 96 | 97 | See the [Nuklear API documenation](https://immediate-mode-ui.github.io/Nuklear/doc/nuklear.html) for more how to use Nuklear. 98 | 99 | ## Comparision 100 | 101 | There are a few other graphical user interface solutions out there for use with raylib. [raygui](https://github.com/raysan5/raygui), [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear), and [ImGui](https://github.com/ocornut/imgui) with [rlImGui](https://github.com/raylib-extras/rlImGui), are popular choices. It's best to choose the GUI that fits your needs best. Generally, if you're unsure which GUI to use with raylib, use [raygui](https://github.com/raysan5/raygui). 102 | 103 | | | [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) | [raygui](https://github.com/raysan5/raygui) | [rlImGui](https://github.com/raylib-extras/rlImGui) | 104 | | ----- |:-------:|:------:|:-----:| 105 | | Only C | :white_check_mark: | :white_check_mark: | C++ | 106 | | Minimal Dependencies | :white_check_mark: | :white_check_mark: | :x: | 107 | | Automatic Layouts | :white_check_mark: | :x: | :white_check_mark: | 108 | | Advanced Controls | :white_check_mark: | :x: | :white_check_mark: | 109 | | Documentation | :white_check_mark: | :x: | :white_check_mark: | 110 | | Industry Standard | :x: | :x: | :white_check_mark: | 111 | | Easy to Use | :x: | :white_check_mark: | :x: | 112 | 113 | ## Development 114 | 115 | While this project uses CMake, CMake is not required in order to use *raylib-nuklear*. 116 | 117 | ``` 118 | git submodule update --init 119 | mkdir build 120 | cd build 121 | cmake .. 122 | make 123 | ./example/raylib-nuklear-example 124 | make test 125 | ``` 126 | 127 | ## License 128 | 129 | *raylib-nuklear* 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. 130 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # raylib 2 | find_package(raylib QUIET) 3 | if (NOT raylib_FOUND) 4 | include(FetchContent) 5 | FetchContent_Declare( 6 | raylib 7 | GIT_REPOSITORY https://github.com/raysan5/raylib.git 8 | GIT_TAG 5.5 9 | GIT_SHALLOW 1 10 | ) 11 | FetchContent_GetProperties(raylib) 12 | if (NOT raylib_POPULATED) # Have we downloaded raylib yet? 13 | set(FETCHCONTENT_QUIET NO) 14 | FetchContent_Populate(raylib) 15 | set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) 16 | set(BUILD_GAMES OFF CACHE BOOL "" FORCE) 17 | add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR}) 18 | endif() 19 | endif() 20 | 21 | # raylib-nuklear-example 22 | add_executable(raylib-nuklear-example 23 | raylib-nuklear-example.c 24 | ) 25 | target_link_libraries(raylib-nuklear-example PUBLIC 26 | raylib 27 | raylib_nuklear 28 | ) 29 | 30 | # raylib-nuklear-demo 31 | add_executable(raylib-nuklear-demo 32 | raylib-nuklear-demo.c 33 | ) 34 | target_link_libraries(raylib-nuklear-demo PUBLIC 35 | raylib 36 | raylib_nuklear 37 | ) 38 | 39 | # raylib-nuklear-font 40 | add_executable(raylib-nuklear-font 41 | raylib-nuklear-font.c 42 | ) 43 | target_link_libraries(raylib-nuklear-font PUBLIC 44 | raylib 45 | raylib_nuklear 46 | ) 47 | 48 | # raylib-nuklear-font 49 | add_executable(raylib-nuklear-font-default 50 | raylib-nuklear-font-default.c 51 | ) 52 | target_link_libraries(raylib-nuklear-font-default PUBLIC 53 | raylib 54 | raylib_nuklear 55 | ) 56 | 57 | # raylib-nuklear-texture 58 | add_executable(raylib-nuklear-texture 59 | raylib-nuklear-texture.c 60 | ) 61 | target_link_libraries(raylib-nuklear-texture PUBLIC 62 | raylib 63 | raylib_nuklear 64 | ) 65 | 66 | # Target C99 67 | set_property(TARGET raylib-nuklear-example PROPERTY C_STANDARD 99) 68 | set_property(TARGET raylib-nuklear-demo PROPERTY C_STANDARD 99) 69 | set_property(TARGET raylib-nuklear-font PROPERTY C_STANDARD 99) 70 | set_property(TARGET raylib-nuklear-texture PROPERTY C_STANDARD 99) 71 | 72 | # Enable warnings 73 | if(MSVC) 74 | target_compile_options(raylib-nuklear-example PRIVATE /W4 /WX) 75 | target_compile_options(raylib-nuklear-demo PRIVATE /W4 /WX) 76 | target_compile_options(raylib-nuklear-font PRIVATE /W4 /WX) 77 | target_compile_options(raylib-nuklear-texture PRIVATE /W4 /WX) 78 | else() 79 | target_compile_options(raylib-nuklear-example PRIVATE -Wall -Wextra -Wpedantic -Werror) 80 | target_compile_options(raylib-nuklear-demo PRIVATE -Wall -Wextra -Wpedantic -Werror) 81 | target_compile_options(raylib-nuklear-font PRIVATE -Wall -Wextra -Wpedantic -Werror) 82 | target_compile_options(raylib-nuklear-texture PRIVATE -Wall -Wextra -Wpedantic -Werror) 83 | endif() 84 | 85 | # Resources 86 | configure_file(resources/anonymous_pro_bold.ttf resources/anonymous_pro_bold.ttf COPYONLY) 87 | configure_file(resources/test-image.png resources/test-image.png COPYONLY) 88 | 89 | # Web Configurations 90 | #if (${PLATFORM} STREQUAL "Web") 91 | if (EMSCRIPTEN) 92 | # Tell Emscripten to build an example.html file. 93 | set_target_properties(raylib-nuklear-demo PROPERTIES SUFFIX ".html") 94 | set_target_properties(raylib-nuklear-demo PROPERTIES OUTPUT_NAME "index") 95 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --shell-file ${CMAKE_CURRENT_SOURCE_DIR}/minshell.html") 96 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3") 97 | add_definitions(-DPLATFORM=Web) 98 | add_definitions(-DCMAKE_BUILD_TYPE=Release) 99 | endif() 100 | -------------------------------------------------------------------------------- /examples/LICENSE: -------------------------------------------------------------------------------- 1 | Fonts used in examples are provided under a free and permissive license. 2 | Check individual licenses for details: 3 | 4 | - [Anonymous Pro] by Mark Simonson - https://fonts.google.com/specimen/Anonymous+Pro 5 | -------------------------------------------------------------------------------- /examples/minshell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | raylib-nuklear: Demo 7 | 8 | 9 | 10 | 28 | 29 | 30 | 31 | 32 | 33 | 47 | {{{ SCRIPT }}} 48 | 49 | 50 | -------------------------------------------------------------------------------- /examples/raylib-nuklear-demo.c: -------------------------------------------------------------------------------- 1 | /* nuklear - 1.32.0 - public domain */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "raylib.h" 14 | 15 | #if defined(PLATFORM_WEB) 16 | #include 17 | #endif 18 | 19 | //#define NK_INCLUDE_FIXED_TYPES 20 | //#define NK_INCLUDE_STANDARD_IO 21 | #define NK_INCLUDE_STANDARD_VARARGS 22 | //#define NK_INCLUDE_DEFAULT_ALLOCATOR 23 | //#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT 24 | //#define NK_INCLUDE_FONT_BAKING 25 | //#define NK_INCLUDE_DEFAULT_FONT 26 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 27 | #define RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT 28 | #include "raylib-nuklear.h" 29 | 30 | #define WINDOW_WIDTH 1200 31 | #define WINDOW_HEIGHT 800 32 | 33 | /* =============================================================== 34 | * 35 | * EXAMPLE 36 | * 37 | * ===============================================================*/ 38 | /* This are some code examples to provide a small overview of what can be 39 | * done with this library. To try out an example uncomment the defines */ 40 | #define INCLUDE_ALL 41 | /*#define INCLUDE_STYLE */ 42 | /*#define INCLUDE_CALCULATOR */ 43 | /*#define INCLUDE_CANVAS */ 44 | /*#define INCLUDE_OVERVIEW */ 45 | /*#define INCLUDE_NODE_EDITOR */ 46 | 47 | #ifdef INCLUDE_ALL 48 | //#define INCLUDE_STYLE 49 | #define INCLUDE_CALCULATOR 50 | #define INCLUDE_CANVAS 51 | #define INCLUDE_OVERVIEW 52 | //#define INCLUDE_NODE_EDITOR 53 | #endif 54 | 55 | #ifdef INCLUDE_STYLE 56 | #include "../vendor/nuklear/demo/style.c" 57 | #endif 58 | #ifdef INCLUDE_CALCULATOR 59 | #include "../vendor/nuklear/demo/common/calculator.c" 60 | #endif 61 | #ifdef INCLUDE_CANVAS 62 | #include "../vendor/nuklear/demo/common/canvas.c" 63 | #endif 64 | #ifdef INCLUDE_OVERVIEW 65 | #include "../vendor/nuklear/demo/common/overview.c" 66 | #endif 67 | #ifdef INCLUDE_NODE_EDITOR 68 | #include "../vendor/nuklear/demo/common/node_editor.c" 69 | #endif 70 | 71 | //---------------------------------------------------------------------------------- 72 | // Global Variables Definition 73 | //---------------------------------------------------------------------------------- 74 | struct nk_context *ctx; 75 | struct nk_colorf bg; 76 | 77 | //---------------------------------------------------------------------------------- 78 | // Module Functions Declaration 79 | //---------------------------------------------------------------------------------- 80 | void UpdateDrawFrame(void); // Update and Draw one frame 81 | 82 | //---------------------------------------------------------------------------------- 83 | // Main Entry Point 84 | //---------------------------------------------------------------------------------- 85 | int main(void) { 86 | // Initialization 87 | //-------------------------------------------------------------------------------------- 88 | InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "[raylib-nuklear] demo"); 89 | SetTargetFPS(60); 90 | 91 | /* GUI */ 92 | const int fontSize = 13; 93 | Font font = LoadFontFromNuklear(fontSize); 94 | ctx = InitNuklearEx(font, fontSize); 95 | bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f; 96 | 97 | /* style.c */ 98 | #ifdef INCLUDE_STYLE 99 | /*set_style(ctx, THEME_WHITE);*/ 100 | /*set_style(ctx, THEME_RED);*/ 101 | /*set_style(ctx, THEME_BLUE);*/ 102 | /*set_style(ctx, THEME_DARK);*/ 103 | #endif 104 | 105 | //-------------------------------------------------------------------------------------- 106 | 107 | // Main game loop 108 | #if defined(PLATFORM_WEB) 109 | emscripten_set_main_loop(UpdateDrawFrame, 0, 1); 110 | #else 111 | while (!WindowShouldClose()) // Detect window close button or ESC key 112 | { 113 | UpdateDrawFrame(); 114 | } 115 | #endif 116 | //-------------------------------------------------------------------------------------- 117 | 118 | // De-Initialization 119 | //-------------------------------------------------------------------------------------- 120 | UnloadNuklear(ctx); // Unload the Nuklear GUI 121 | CloseWindow(); 122 | //-------------------------------------------------------------------------------------- 123 | 124 | return 0; 125 | } 126 | 127 | 128 | void UpdateDrawFrame(void) { 129 | /* Input */ 130 | UpdateNuklear(ctx); 131 | 132 | /* GUI */ 133 | if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), 134 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| 135 | NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) 136 | { 137 | enum {EASY, HARD}; 138 | static int op = EASY; 139 | static int property = 20; 140 | 141 | nk_layout_row_static(ctx, 30, 80, 1); 142 | if (nk_button_label(ctx, "button")) 143 | TraceLog(LOG_INFO, "button pressed!"); 144 | nk_layout_row_dynamic(ctx, 30, 2); 145 | if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; 146 | if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; 147 | nk_layout_row_dynamic(ctx, 22, 1); 148 | nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); 149 | 150 | nk_layout_row_dynamic(ctx, 20, 1); 151 | nk_label(ctx, "background:", NK_TEXT_LEFT); 152 | nk_layout_row_dynamic(ctx, 25, 1); 153 | if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) { 154 | nk_layout_row_dynamic(ctx, 120, 1); 155 | bg = nk_color_picker(ctx, bg, NK_RGBA); 156 | nk_layout_row_dynamic(ctx, 25, 1); 157 | bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f); 158 | bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f); 159 | bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f); 160 | bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f); 161 | nk_combo_end(ctx); 162 | } 163 | } 164 | nk_end(ctx); 165 | 166 | /* -------------- EXAMPLES ---------------- */ 167 | #ifdef INCLUDE_CALCULATOR 168 | calculator(ctx); 169 | #endif 170 | #ifdef INCLUDE_CANVAS 171 | canvas(ctx); 172 | #endif 173 | #ifdef INCLUDE_OVERVIEW 174 | overview(ctx); 175 | #endif 176 | #ifdef INCLUDE_NODE_EDITOR 177 | node_editor(ctx); 178 | #endif 179 | /* ----------------------------------------- */ 180 | 181 | /* Draw */ 182 | BeginDrawing(); 183 | { 184 | ClearBackground(ColorFromNuklearF(bg)); 185 | DrawNuklear(ctx); 186 | } 187 | EndDrawing(); 188 | } 189 | -------------------------------------------------------------------------------- /examples/raylib-nuklear-example.c: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-nuklear-example - Example of using Nuklear with Raylib. 4 | * 5 | * LICENSE: zlib/libpng 6 | * 7 | * nuklear_raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | * BSD-like license that allows static linking with closed source software: 9 | * 10 | * Copyright (c) 2020 Rob Loach (@RobLoach) 11 | * 12 | * This software is provided "as-is", without any express or implied warranty. In no event 13 | * will the authors be held liable for any damages arising from the use of this software. 14 | * 15 | * Permission is granted to anyone to use this software for any purpose, including commercial 16 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not claim that you 19 | * wrote the original software. If you use this software in a product, an acknowledgment 20 | * in the product documentation would be appreciated but is not required. 21 | * 22 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 23 | * as being the original software. 24 | * 25 | * 3. This notice may not be removed or altered from any source distribution. 26 | * 27 | **********************************************************************************************/ 28 | 29 | #include "raylib.h" 30 | 31 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 32 | #include "raylib-nuklear.h" 33 | 34 | int main(void) 35 | { 36 | // Initialization 37 | //-------------------------------------------------------------------------------------- 38 | const int screenWidth = 700; 39 | const int screenHeight = 394; 40 | InitWindow(screenWidth, screenHeight, "[raylib-nuklear] example"); 41 | 42 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second 43 | //-------------------------------------------------------------------------------------- 44 | 45 | /* GUI */ 46 | struct nk_colorf bg = ColorToNuklearF(SKYBLUE); 47 | struct nk_context *ctx = InitNuklear(0); 48 | 49 | // Main game loop 50 | while (!WindowShouldClose()) // Detect window close button or ESC key 51 | { 52 | // Update 53 | UpdateNuklear(ctx); 54 | 55 | // GUI 56 | if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), 57 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| 58 | NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) 59 | { 60 | enum {EASY, HARD}; 61 | static int op = EASY; 62 | static int property = 20; 63 | nk_layout_row_static(ctx, 30, 80, 1); 64 | if (nk_button_label(ctx, "button")) 65 | TraceLog(LOG_INFO, "button pressed"); 66 | 67 | nk_layout_row_dynamic(ctx, 30, 2); 68 | if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; 69 | if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; 70 | 71 | nk_layout_row_dynamic(ctx, 25, 1); 72 | nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); 73 | 74 | nk_layout_row_dynamic(ctx, 20, 1); 75 | nk_label(ctx, "background:", NK_TEXT_LEFT); 76 | nk_layout_row_dynamic(ctx, 25, 1); 77 | if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) { 78 | nk_layout_row_dynamic(ctx, 120, 1); 79 | bg = nk_color_picker(ctx, bg, NK_RGBA); 80 | nk_layout_row_dynamic(ctx, 25, 1); 81 | bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f); 82 | bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f); 83 | bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f); 84 | bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f); 85 | nk_combo_end(ctx); 86 | } 87 | } 88 | 89 | nk_end(ctx); 90 | 91 | // Draw 92 | //---------------------------------------------------------------------------------- 93 | BeginDrawing(); 94 | 95 | ClearBackground(ColorFromNuklearF(bg)); 96 | 97 | DrawNuklear(ctx); 98 | 99 | EndDrawing(); 100 | //---------------------------------------------------------------------------------- 101 | } 102 | 103 | // De-Initialization 104 | //-------------------------------------------------------------------------------------- 105 | UnloadNuklear(ctx); // Unload the Nuklear GUI 106 | CloseWindow(); 107 | //-------------------------------------------------------------------------------------- 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /examples/raylib-nuklear-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobLoach/raylib-nuklear/d2bd2b7b3cef4831c0a57ee1b0e11a76a9fe1c19/examples/raylib-nuklear-example.png -------------------------------------------------------------------------------- /examples/raylib-nuklear-font-default.c: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-nuklear-font - Example of using Nuklear with a custom Raylib font. 4 | * 5 | * LICENSE: zlib/libpng 6 | * 7 | * raylib-nuklear is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | * BSD-like license that allows static linking with closed source software: 9 | * 10 | * Copyright (c) 2020 Rob Loach (@RobLoach) 11 | * 12 | * This software is provided "as-is", without any express or implied warranty. In no event 13 | * will the authors be held liable for any damages arising from the use of this software. 14 | * 15 | * Permission is granted to anyone to use this software for any purpose, including commercial 16 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not claim that you 19 | * wrote the original software. If you use this software in a product, an acknowledgment 20 | * in the product documentation would be appreciated but is not required. 21 | * 22 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 23 | * as being the original software. 24 | * 25 | * 3. This notice may not be removed or altered from any source distribution. 26 | * 27 | **********************************************************************************************/ 28 | 29 | #include "raylib.h" 30 | 31 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 32 | #define RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT 33 | #include "raylib-nuklear.h" 34 | 35 | int main(void) 36 | { 37 | // Initialization 38 | //-------------------------------------------------------------------------------------- 39 | const int screenWidth = 800; 40 | const int screenHeight = 450; 41 | const int fontSize = 14; 42 | 43 | InitWindow(screenWidth, screenHeight, "[raylib-nuklear] font example"); 44 | Font font = LoadFontFromNuklear(0); 45 | 46 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second 47 | //-------------------------------------------------------------------------------------- 48 | 49 | /* GUI */ 50 | struct nk_colorf bg = ColorToNuklearF(SKYBLUE); 51 | struct nk_context *ctx = InitNuklearEx(font, 0); 52 | 53 | // Main game loop 54 | while (!WindowShouldClose()) // Detect window close button or ESC key 55 | { 56 | // Update 57 | UpdateNuklear(ctx); 58 | 59 | // GUI 60 | if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), 61 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| 62 | NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) 63 | { 64 | enum {EASY, HARD}; 65 | static int op = EASY; 66 | static int property = 20; 67 | nk_layout_row_static(ctx, 30, 80, 1); 68 | if (nk_button_label(ctx, "button")) 69 | TraceLog(LOG_INFO, "button pressed"); 70 | 71 | nk_layout_row_dynamic(ctx, 30, 2); 72 | if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; 73 | if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; 74 | 75 | nk_layout_row_dynamic(ctx, 25, 1); 76 | nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); 77 | 78 | nk_layout_row_dynamic(ctx, 20, 1); 79 | nk_label(ctx, "background:", NK_TEXT_LEFT); 80 | nk_layout_row_dynamic(ctx, 25, 1); 81 | if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) { 82 | nk_layout_row_dynamic(ctx, 120, 1); 83 | bg = nk_color_picker(ctx, bg, NK_RGBA); 84 | nk_layout_row_dynamic(ctx, 25, 1); 85 | bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f); 86 | bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f); 87 | bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f); 88 | bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f); 89 | nk_combo_end(ctx); 90 | } 91 | } 92 | 93 | nk_end(ctx); 94 | 95 | // Draw 96 | //---------------------------------------------------------------------------------- 97 | BeginDrawing(); 98 | 99 | ClearBackground(ColorFromNuklearF(bg)); 100 | 101 | DrawNuklear(ctx); 102 | 103 | EndDrawing(); 104 | //---------------------------------------------------------------------------------- 105 | } 106 | 107 | // De-Initialization 108 | //-------------------------------------------------------------------------------------- 109 | UnloadNuklear(ctx); // Unload the Nuklear GUI 110 | UnloadFont(font); 111 | CloseWindow(); 112 | //-------------------------------------------------------------------------------------- 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /examples/raylib-nuklear-font.c: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-nuklear-font - Example of using Nuklear with a custom Raylib font. 4 | * 5 | * LICENSE: zlib/libpng 6 | * 7 | * raylib-nuklear is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | * BSD-like license that allows static linking with closed source software: 9 | * 10 | * Copyright (c) 2020 Rob Loach (@RobLoach) 11 | * 12 | * This software is provided "as-is", without any express or implied warranty. In no event 13 | * will the authors be held liable for any damages arising from the use of this software. 14 | * 15 | * Permission is granted to anyone to use this software for any purpose, including commercial 16 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not claim that you 19 | * wrote the original software. If you use this software in a product, an acknowledgment 20 | * in the product documentation would be appreciated but is not required. 21 | * 22 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 23 | * as being the original software. 24 | * 25 | * 3. This notice may not be removed or altered from any source distribution. 26 | * 27 | **********************************************************************************************/ 28 | 29 | #include "raylib.h" 30 | 31 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 32 | #include "raylib-nuklear.h" 33 | 34 | int main(void) 35 | { 36 | // Initialization 37 | //-------------------------------------------------------------------------------------- 38 | const int screenWidth = 800; 39 | const int screenHeight = 450; 40 | const int fontSize = 18; 41 | 42 | InitWindow(screenWidth, screenHeight, "[raylib-nuklear] font example"); 43 | Font font = LoadFontEx("resources/anonymous_pro_bold.ttf", fontSize, NULL, 0); 44 | 45 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second 46 | //-------------------------------------------------------------------------------------- 47 | 48 | /* GUI */ 49 | struct nk_colorf bg = ColorToNuklearF(SKYBLUE); 50 | struct nk_context *ctx = InitNuklearEx(font, fontSize); 51 | 52 | // Main game loop 53 | while (!WindowShouldClose()) // Detect window close button or ESC key 54 | { 55 | // Update 56 | UpdateNuklear(ctx); 57 | 58 | // GUI 59 | if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), 60 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| 61 | NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) 62 | { 63 | enum {EASY, HARD}; 64 | static int op = EASY; 65 | static int property = 20; 66 | nk_layout_row_static(ctx, 30, 80, 1); 67 | if (nk_button_label(ctx, "button")) 68 | TraceLog(LOG_INFO, "button pressed"); 69 | 70 | nk_layout_row_dynamic(ctx, 30, 2); 71 | if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; 72 | if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; 73 | 74 | nk_layout_row_dynamic(ctx, 25, 1); 75 | nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); 76 | 77 | nk_layout_row_dynamic(ctx, 20, 1); 78 | nk_label(ctx, "background:", NK_TEXT_LEFT); 79 | nk_layout_row_dynamic(ctx, 25, 1); 80 | if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) { 81 | nk_layout_row_dynamic(ctx, 120, 1); 82 | bg = nk_color_picker(ctx, bg, NK_RGBA); 83 | nk_layout_row_dynamic(ctx, 25, 1); 84 | bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f); 85 | bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f); 86 | bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f); 87 | bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f); 88 | nk_combo_end(ctx); 89 | } 90 | } 91 | 92 | nk_end(ctx); 93 | 94 | // Draw 95 | //---------------------------------------------------------------------------------- 96 | BeginDrawing(); 97 | 98 | ClearBackground(ColorFromNuklearF(bg)); 99 | 100 | DrawNuklear(ctx); 101 | 102 | EndDrawing(); 103 | //---------------------------------------------------------------------------------- 104 | } 105 | 106 | // De-Initialization 107 | //-------------------------------------------------------------------------------------- 108 | UnloadNuklear(ctx); // Unload the Nuklear GUI 109 | UnloadFont(font); 110 | CloseWindow(); 111 | //-------------------------------------------------------------------------------------- 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /examples/raylib-nuklear-texture.c: -------------------------------------------------------------------------------- 1 | /* =============================================================== 2 | * 3 | * EXAMPLE 4 | * 5 | * ===============================================================*/ 6 | /* 7 | This example shows how to use the image API from raylib nuklear. 8 | And then display it. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 16 | #include "raylib-nuklear.h" 17 | 18 | int main(void) 19 | { 20 | InitWindow(1280, 720, "[raylib-nuklear] - Texture/Image"); 21 | 22 | // Initialize the context 23 | struct nk_context* ctx = InitNuklear(20); 24 | 25 | // Scale up the Nuklear GUI 26 | SetNuklearScaling(ctx, 1.2f); 27 | 28 | // Load the nk_image 29 | struct nk_image img = LoadNuklearImage("resources/test-image.png"); 30 | 31 | while (!WindowShouldClose()) 32 | { 33 | // Input 34 | UpdateNuklear(ctx); 35 | 36 | // The window called "Image example" is opend 37 | if(nk_begin(ctx, "Image example", nk_rect(300, 100, img.w, img.h + 50), NK_WINDOW_MINIMIZABLE|NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) 38 | { 39 | // Setup the layout 40 | nk_layout_row_static(ctx, img.h, img.w, 1); 41 | 42 | // Draw the image 43 | nk_image(ctx, img); 44 | } 45 | nk_end(ctx); 46 | 47 | // Draw the GUI 48 | BeginDrawing(); 49 | ClearBackground(RAYWHITE); 50 | DrawNuklear(ctx); 51 | EndDrawing(); 52 | } 53 | 54 | // Unload the Nuklear image 55 | UnloadNuklearImage(img); 56 | 57 | CloseWindow(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /examples/resources/anonymous_pro_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobLoach/raylib-nuklear/d2bd2b7b3cef4831c0a57ee1b0e11a76a9fe1c19/examples/resources/anonymous_pro_bold.ttf -------------------------------------------------------------------------------- /examples/resources/test-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobLoach/raylib-nuklear/d2bd2b7b3cef4831c0a57ee1b0e11a76a9fe1c19/examples/resources/test-image.png -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # raylib_nuklear 2 | add_library(raylib_nuklear INTERFACE) 3 | target_include_directories(raylib_nuklear INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) 4 | install(FILES 5 | raylib-nuklear.h 6 | raylib-nuklear-font.h 7 | nuklear.h 8 | DESTINATION include 9 | ) 10 | -------------------------------------------------------------------------------- /include/raylib-nuklear.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-nuklear v5.5.0 - Nuklear GUI for Raylib. 4 | * 5 | * FEATURES: 6 | * - Use the Nuklear immediate-mode graphical user interface in raylib. 7 | * 8 | * DEPENDENCIES: 9 | * - raylib 5.5+ https://www.raylib.com/ 10 | * - Nuklear https://github.com/Immediate-Mode-UI/Nuklear 11 | * 12 | * LICENSE: zlib/libpng 13 | * 14 | * raylib-nuklear is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 15 | * BSD-like license that allows static linking with closed source software: 16 | * 17 | * Copyright (c) 2020 Rob Loach (@RobLoach) 18 | * 19 | * This software is provided "as-is", without any express or implied warranty. In no event 20 | * will the authors be held liable for any damages arising from the use of this software. 21 | * 22 | * Permission is granted to anyone to use this software for any purpose, including commercial 23 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 24 | * 25 | * 1. The origin of this software must not be misrepresented; you must not claim that you 26 | * wrote the original software. If you use this software in a product, an acknowledgment 27 | * in the product documentation would be appreciated but is not required. 28 | * 29 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 30 | * as being the original software. 31 | * 32 | * 3. This notice may not be removed or altered from any source distribution. 33 | * 34 | **********************************************************************************************/ 35 | 36 | #ifndef RAYLIB_NUKLEAR_H 37 | #define RAYLIB_NUKLEAR_H 38 | 39 | #include "raylib.h" 40 | 41 | // Nuklear defines 42 | #define NK_INCLUDE_FIXED_TYPES 43 | #define NK_INCLUDE_STANDARD_VARARGS 44 | #define NK_INCLUDE_STANDARD_BOOL 45 | #define NK_INCLUDE_COMMAND_USERDATA 46 | #define NK_KEYSTATE_BASED_INPUT 47 | 48 | #ifndef NK_ASSERT 49 | #ifdef NDEBUG 50 | #define NK_ASSERT(condition) ((void)0) 51 | #else 52 | #define NK_ASSERT(condition) do { if (!(condition)) { TraceLog(LOG_ERROR, "NUKLEAR: Failed assert \"%s\" (%s:%i)", #condition, "nuklear.h", __LINE__); }} while (0) 53 | #endif // NDEBUG 54 | #endif // NK_ASSERT 55 | 56 | #include "nuklear.h" 57 | 58 | #ifdef __cplusplus 59 | extern "C" { 60 | #endif 61 | 62 | NK_API struct nk_context* InitNuklear(int fontSize); // Initialize the Nuklear GUI context using raylib's font 63 | NK_API struct nk_context* InitNuklearEx(Font font, float fontSize); // Initialize the Nuklear GUI context, with a custom font 64 | NK_API Font LoadFontFromNuklear(int fontSize); // Loads the default Nuklear font 65 | NK_API void UpdateNuklear(struct nk_context * ctx); // Update the input state and internal components for Nuklear 66 | NK_API void UpdateNuklearEx(struct nk_context * ctx, float deltaTime); // Update the input state and internal components for Nuklear, with a custom frame time 67 | NK_API void DrawNuklear(struct nk_context * ctx); // Render the Nuklear GUI on the screen 68 | NK_API void UnloadNuklear(struct nk_context * ctx); // Deinitialize the Nuklear context 69 | NK_API struct nk_color ColorToNuklear(Color color); // Convert a raylib Color to a Nuklear color object 70 | NK_API struct nk_colorf ColorToNuklearF(Color color); // Convert a raylib Color to a Nuklear floating color 71 | NK_API struct Color ColorFromNuklear(struct nk_color color); // Convert a Nuklear color to a raylib Color 72 | NK_API struct Color ColorFromNuklearF(struct nk_colorf color); // Convert a Nuklear floating color to a raylib Color 73 | NK_API struct Rectangle RectangleFromNuklear(struct nk_context * ctx, struct nk_rect rect); // Convert a Nuklear rectangle to a raylib Rectangle 74 | NK_API struct nk_rect RectangleToNuklear(struct nk_context * ctx, Rectangle rect); // Convert a raylib Rectangle to a Nuklear Rectangle 75 | NK_API struct nk_image TextureToNuklear(Texture tex); // Convert a raylib Texture to A Nuklear image 76 | NK_API struct Texture TextureFromNuklear(struct nk_image img); // Convert a Nuklear image to a raylib Texture 77 | NK_API struct nk_image LoadNuklearImage(const char* path); // Load a Nuklear image 78 | NK_API void UnloadNuklearImage(struct nk_image img); // Unload a Nuklear image. And free its data 79 | NK_API void CleanupNuklearImage(struct nk_image img); // Frees the data stored by the Nuklear image 80 | NK_API void SetNuklearScaling(struct nk_context * ctx, float scaling); // Sets the scaling for the given Nuklear context 81 | NK_API float GetNuklearScaling(struct nk_context * ctx); // Retrieves the scaling of the given Nuklear context 82 | 83 | // Internal Nuklear functions 84 | NK_API float nk_raylib_font_get_text_width(nk_handle handle, float height, const char *text, int len); 85 | NK_API float nk_raylib_font_get_text_width_user_font(nk_handle handle, float height, const char *text, int len); 86 | NK_API void nk_raylib_clipboard_paste(nk_handle usr, struct nk_text_edit *edit); 87 | NK_API void nk_raylib_clipboard_copy(nk_handle usr, const char *text, int len); 88 | NK_API void* nk_raylib_malloc(nk_handle unused, void *old, nk_size size); 89 | NK_API void nk_raylib_mfree(nk_handle unused, void *ptr); 90 | NK_API struct nk_context* InitNuklearContext(struct nk_user_font* userFont); 91 | NK_API void nk_raylib_input_keyboard(struct nk_context * ctx); 92 | NK_API void nk_raylib_input_mouse(struct nk_context * ctx); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif // RAYLIB_NUKLEAR_H 99 | 100 | #ifdef RAYLIB_NUKLEAR_IMPLEMENTATION 101 | #ifndef RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE 102 | #define RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE 103 | 104 | #include // NULL 105 | #include // cosf, sinf, sqrtf 106 | 107 | // Math 108 | #ifndef NK_COS 109 | #define NK_COS cosf 110 | #endif // NK_COS 111 | #ifndef NK_SIN 112 | #define NK_SIN sinf 113 | #endif // NK_SIN 114 | #ifndef NK_INV_SQRT 115 | #define NK_INV_SQRT(value) (1.0f / sqrtf(value)) 116 | #endif // NK_INV_SQRT 117 | 118 | #define NK_IMPLEMENTATION 119 | #include "nuklear.h" 120 | 121 | #ifdef __cplusplus 122 | extern "C" { 123 | #endif 124 | 125 | #ifndef RAYLIB_NUKLEAR_DEFAULT_FONTSIZE 126 | /** 127 | * The default font size that is used when a font size is not provided. 128 | */ 129 | #define RAYLIB_NUKLEAR_DEFAULT_FONTSIZE 13 130 | #endif // RAYLIB_NUKLEAR_DEFAULT_FONTSIZE 131 | 132 | /* 133 | * Spacing is determined by the font size multiplied by RAYLIB_NUKLEAR_FONT_SPACING_RATIO. 134 | */ 135 | #ifndef RAYLIB_NUKLEAR_FONT_SPACING_RATIO 136 | #define RAYLIB_NUKLEAR_FONT_SPACING_RATIO 0.01f 137 | #endif // RAYLIB_NUKLEAR_FONT_SPACING_RATIO 138 | 139 | #ifndef RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 140 | /** 141 | * The amount of segments used when drawing an arc. 142 | * 143 | * @see NK_COMMAND_ARC_FILLED 144 | */ 145 | #define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 20 146 | #endif // RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 147 | 148 | #ifdef RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT 149 | #include "raylib-nuklear-font.h" 150 | #endif 151 | 152 | /** 153 | * The user data that's leverages internally through Nuklear. 154 | */ 155 | typedef struct NuklearUserData { 156 | float scaling; // The scaling of the Nuklear user interface. 157 | } NuklearUserData; 158 | 159 | /** 160 | * Nuklear callback; Get the width of the given text. 161 | * 162 | * @internal 163 | */ 164 | NK_API float 165 | nk_raylib_font_get_text_width(nk_handle handle, float height, const char *text, int len) 166 | { 167 | NK_UNUSED(handle); 168 | 169 | if (len > 0) { 170 | // Grab the text with the cropped length so that it only measures the desired string length. 171 | const char* subtext = TextSubtext(text, 0, len); 172 | 173 | // Spacing is determined by the font size multiplied by RAYLIB_NUKLEAR_FONT_SPACING_RATIO. 174 | // Raylib only counts the spacing between characters, but Nuklear expects one spacing to be 175 | // counter for every character in the string: 176 | return (float)MeasureText(subtext, (int)height) + height * RAYLIB_NUKLEAR_FONT_SPACING_RATIO; 177 | } 178 | 179 | return 0; 180 | } 181 | 182 | /** 183 | * Nuklear callback; Get the width of the given text (userFont version) 184 | * 185 | * @internal 186 | */ 187 | NK_API float 188 | nk_raylib_font_get_text_width_user_font(nk_handle handle, float height, const char *text, int len) 189 | { 190 | if (len > 0) { 191 | // Grab the text with the cropped length so that it only measures the desired string length. 192 | const char* subtext = TextSubtext(text, 0, len); 193 | 194 | // Spacing is determined by the font size multiplied by RAYLIB_NUKLEAR_FONT_SPACING_RATIO. 195 | // Raylib only counts the spacing between characters, but Nuklear expects one spacing to be 196 | // counter for every character in the string: 197 | return MeasureTextEx(*(Font*)handle.ptr, subtext, height, height * RAYLIB_NUKLEAR_FONT_SPACING_RATIO).x + height * RAYLIB_NUKLEAR_FONT_SPACING_RATIO; 198 | } 199 | 200 | return 0; 201 | } 202 | 203 | /** 204 | * Nuklear callback; Paste the current clipboard. 205 | * 206 | * @internal 207 | */ 208 | NK_API void 209 | nk_raylib_clipboard_paste(nk_handle usr, struct nk_text_edit *edit) 210 | { 211 | const char *text = GetClipboardText(); 212 | NK_UNUSED(usr); 213 | if (text != NULL) { 214 | nk_textedit_paste(edit, text, (int)TextLength(text)); 215 | } 216 | } 217 | 218 | /** 219 | * Nuklear callback; Copy the given text. 220 | * 221 | * @internal 222 | */ 223 | NK_API void 224 | nk_raylib_clipboard_copy(nk_handle usr, const char *text, int len) 225 | { 226 | NK_UNUSED(usr); 227 | char* trimmedText = (char*)MemAlloc((unsigned int)(sizeof(char) * (size_t)(len + 1))); 228 | if(!trimmedText) 229 | return; 230 | nk_memcopy(trimmedText, text, (nk_size)len); 231 | trimmedText[len] = 0; 232 | SetClipboardText(trimmedText); 233 | MemFree(trimmedText); 234 | } 235 | 236 | /** 237 | * Nuklear callback; Allocate memory for Nuklear. 238 | * 239 | * @internal 240 | */ 241 | NK_API void* 242 | nk_raylib_malloc(nk_handle unused, void *old, nk_size size) 243 | { 244 | NK_UNUSED(unused); 245 | NK_UNUSED(old); 246 | return MemAlloc((unsigned int)size); 247 | } 248 | 249 | /** 250 | * Nuklear callback; Free memory for Nuklear. 251 | */ 252 | NK_API void 253 | nk_raylib_mfree(nk_handle unused, void *ptr) 254 | { 255 | NK_UNUSED(unused); 256 | MemFree(ptr); 257 | } 258 | 259 | /** 260 | * Initialize the Nuklear context for use with Raylib, with the given Nuklear user font. 261 | * 262 | * @param userFont The Nuklear user font to initialize the Nuklear context with. 263 | * 264 | * @internal 265 | */ 266 | NK_API struct nk_context* 267 | InitNuklearContext(struct nk_user_font* userFont) 268 | { 269 | struct nk_context* ctx = (struct nk_context*)MemAlloc(sizeof(struct nk_context)); 270 | if (ctx == NULL) { 271 | TraceLog(LOG_ERROR, "NUKLEAR: Failed to initialize nuklear memory"); 272 | return NULL; 273 | } 274 | 275 | struct NuklearUserData* userData = (struct NuklearUserData*)MemAlloc(sizeof(struct NuklearUserData)); 276 | if (userData == NULL) { 277 | TraceLog(LOG_ERROR, "NUKLEAR: Failed to initialize nuklear user data"); 278 | MemFree(ctx); 279 | return NULL; 280 | } 281 | 282 | // Allocator 283 | struct nk_allocator alloc; 284 | alloc.userdata = nk_handle_ptr(0); 285 | alloc.alloc = nk_raylib_malloc; 286 | alloc.free = nk_raylib_mfree; 287 | 288 | // Initialize the context. 289 | if (!nk_init(ctx, &alloc, userFont)) { 290 | TraceLog(LOG_ERROR, "NUKLEAR: Failed to initialize nuklear"); 291 | MemFree(ctx); 292 | MemFree(userData); 293 | return NULL; 294 | } 295 | 296 | // Clipboard 297 | ctx->clip.copy = nk_raylib_clipboard_copy; 298 | ctx->clip.paste = nk_raylib_clipboard_paste; 299 | ctx->clip.userdata = nk_handle_ptr(0); 300 | 301 | // Set the internal user data. 302 | userData->scaling = 1.0f; 303 | nk_handle userDataHandle; 304 | userDataHandle.id = 1; 305 | userDataHandle.ptr = (void*)userData; 306 | nk_set_user_data(ctx, userDataHandle); 307 | 308 | TraceLog(LOG_INFO, "NUKLEAR: Initialized GUI"); 309 | 310 | return ctx; 311 | } 312 | 313 | /** 314 | * Initialize the Nuklear context for use with Raylib. 315 | * 316 | * @param fontSize The size of the font to use for GUI text. Use 0 to use the default font size of 10. 317 | * 318 | * @return The nuklear context, or NULL on error. 319 | */ 320 | NK_API struct nk_context* 321 | InitNuklear(int fontSize) 322 | { 323 | // User font. 324 | struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font)); 325 | 326 | // Use the default font size if desired. 327 | if (fontSize <= 0) { 328 | fontSize = RAYLIB_NUKLEAR_DEFAULT_FONTSIZE; 329 | } 330 | 331 | userFont->height = (float)fontSize; 332 | userFont->width = nk_raylib_font_get_text_width; 333 | userFont->userdata = nk_handle_ptr(0); 334 | 335 | // Nuklear context. 336 | return InitNuklearContext(userFont); 337 | } 338 | 339 | /** 340 | * Initialize the Nuklear context for use with Raylib, with a supplied custom font. 341 | * 342 | * @param font The custom raylib font to use with Nuklear. 343 | * @param fontSize The desired size of the font. Use 0 to set the default size of 10. 344 | * 345 | * @return The nuklear context, or NULL on error. 346 | */ 347 | NK_API struct nk_context* 348 | InitNuklearEx(Font font, float fontSize) 349 | { 350 | // Copy the font to a new raylib font pointer. 351 | struct Font* newFont = (struct Font*)MemAlloc(sizeof(struct Font)); 352 | 353 | // Use the default font size if desired. 354 | if (fontSize <= 0.0f) { 355 | fontSize = (float)RAYLIB_NUKLEAR_DEFAULT_FONTSIZE; 356 | } 357 | newFont->baseSize = font.baseSize; 358 | newFont->glyphCount = font.glyphCount; 359 | newFont->glyphPadding = font.glyphPadding; 360 | newFont->glyphs = font.glyphs; 361 | newFont->recs = font.recs; 362 | newFont->texture = font.texture; 363 | 364 | // Create the nuklear user font. 365 | struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font)); 366 | userFont->userdata = nk_handle_ptr(newFont); 367 | userFont->height = fontSize; 368 | userFont->width = nk_raylib_font_get_text_width_user_font; 369 | 370 | // Nuklear context. 371 | return InitNuklearContext(userFont); 372 | } 373 | 374 | /** 375 | * Load the default Nuklear font. Requires `RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT` to be defined. 376 | * 377 | * @param size The size of the font to load (optional). Provide 0 if you'd like to use the default size from Nuklear. 378 | * 379 | * @return The loaded font, or an empty font on error. 380 | * 381 | * @code 382 | * #define RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT 383 | * #include "raylib-nuklear.h" 384 | * Font font = LoadFontFromNuklear(0); 385 | * @endcode 386 | */ 387 | NK_API Font LoadFontFromNuklear(int size) { 388 | #ifndef RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT 389 | (void)size; 390 | TraceLog(LOG_ERROR, "NUKLEAR: RAYLIB_NUKLEAR_INCLUDE_DEFAULT_FONT must be defined to use LoadFontFromNuklear()"); 391 | return CLITERAL(Font) {0}; 392 | #else 393 | if (size <= 0) { 394 | size = RAYLIB_NUKLEAR_DEFAULT_FONTSIZE; 395 | } 396 | 397 | #ifndef RAYLIB_NUKLEAR_DEFAULT_FONT_GLYPHS 398 | /** 399 | * The amount of glyphs to load for the default font. 400 | */ 401 | #define RAYLIB_NUKLEAR_DEFAULT_FONT_GLYPHS 95 402 | #endif 403 | 404 | return LoadFontFromMemory(".ttf", RAYLIB_NUKLEAR_DEFAULT_FONT_NAME, RAYLIB_NUKLEAR_DEFAULT_FONT_SIZE, size, NULL, RAYLIB_NUKLEAR_DEFAULT_FONT_GLYPHS); 405 | #endif 406 | } 407 | 408 | /** 409 | * Convert the given Nuklear color to a raylib color. 410 | */ 411 | NK_API Color 412 | ColorFromNuklear(struct nk_color color) 413 | { 414 | Color rc; 415 | rc.a = color.a; 416 | rc.r = color.r; 417 | rc.g = color.g; 418 | rc.b = color.b; 419 | return rc; 420 | } 421 | 422 | /** 423 | * Convert the given raylib color to a Nuklear color. 424 | */ 425 | NK_API struct nk_color 426 | ColorToNuklear(Color color) 427 | { 428 | struct nk_color rc; 429 | rc.a = color.a; 430 | rc.r = color.r; 431 | rc.g = color.g; 432 | rc.b = color.b; 433 | return rc; 434 | } 435 | 436 | /** 437 | * Convert the given Nuklear float color to a raylib color. 438 | */ 439 | NK_API Color 440 | ColorFromNuklearF(struct nk_colorf color) 441 | { 442 | return ColorFromNuklear(nk_rgba_cf(color)); 443 | } 444 | 445 | /** 446 | * Convert the given raylib color to a raylib float color. 447 | */ 448 | NK_API struct nk_colorf 449 | ColorToNuklearF(Color color) 450 | { 451 | return nk_color_cf(ColorToNuklear(color)); 452 | } 453 | 454 | /** 455 | * Draw the given Nuklear context in raylib. 456 | * 457 | * @param ctx The nuklear context. 458 | */ 459 | NK_API void 460 | DrawNuklear(struct nk_context * ctx) 461 | { 462 | // Protect against drawing when there's nothing to draw. 463 | if (ctx == NULL) { 464 | return; 465 | } 466 | 467 | const struct nk_command *cmd; 468 | const float scale = GetNuklearScaling(ctx); 469 | 470 | nk_foreach(cmd, ctx) { 471 | switch (cmd->type) { 472 | case NK_COMMAND_NOP: { 473 | break; 474 | } 475 | 476 | case NK_COMMAND_SCISSOR: { 477 | // TODO(RobLoach): Verify if NK_COMMAND_SCISSOR works. 478 | const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; 479 | BeginScissorMode((int)(s->x * scale), (int)(s->y * scale), (int)(s->w * scale), (int)(s->h * scale)); 480 | } break; 481 | 482 | case NK_COMMAND_LINE: { 483 | const struct nk_command_line *l = (const struct nk_command_line *)cmd; 484 | Color color = ColorFromNuklear(l->color); 485 | Vector2 startPos = CLITERAL(Vector2) {(float)l->begin.x * scale, (float)l->begin.y * scale}; 486 | Vector2 endPos = CLITERAL(Vector2) {(float)l->end.x * scale, (float)l->end.y * scale}; 487 | DrawLineEx(startPos, endPos, l->line_thickness * scale, color); 488 | } break; 489 | 490 | case NK_COMMAND_CURVE: { 491 | const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; 492 | Color color = ColorFromNuklear(q->color); 493 | Vector2 begin = CLITERAL(Vector2) {(float)q->begin.x * scale, (float)q->begin.y * scale}; 494 | Vector2 controlPoint1 = CLITERAL(Vector2) {(float)q->ctrl[0].x * scale, (float)q->ctrl[0].y * scale}; 495 | Vector2 controlPoint2 = CLITERAL(Vector2) {(float)q->ctrl[1].x * scale, (float)q->ctrl[1].y * scale}; 496 | Vector2 end = CLITERAL(Vector2) {(float)q->end.x * scale, (float)q->end.y * scale}; 497 | DrawSplineSegmentBezierCubic(begin, controlPoint1, controlPoint2, end, (float)q->line_thickness * scale, color); 498 | } break; 499 | 500 | case NK_COMMAND_RECT: { 501 | const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; 502 | Color color = ColorFromNuklear(r->color); 503 | Rectangle rect = CLITERAL(Rectangle) {(float)r->x * scale, (float)r->y * scale, (float)r->w * scale, (float)r->h * scale}; 504 | float roundness = (rect.width > rect.height) ? 505 | ((2 * r->rounding * scale)/rect.height) : ((2 * r->rounding * scale)/rect.width); 506 | roundness = NK_CLAMP(0.0f, roundness, 1.0f); 507 | if (roundness > 0.0f) { 508 | // DrawRectangleRoundedLines doesn't work in the same way as DrawRectangleLinesEx and it draws 509 | // the outline outside the region defined by the rectangle. To compensate for that, shrink 510 | // the rectangle by the thickness plus 1 (due to inconsistencies from DrawRectangleRoundedLines): 511 | rect.x += ((float) r->line_thickness) * scale + 1.0f; 512 | rect.y += ((float) r->line_thickness) * scale + 1.0f; 513 | rect.width = NK_MAX(rect.width - (2 * ((float) r->line_thickness) * scale + 1.0f), 0.0f); 514 | rect.height = NK_MAX(rect.height - (2 * ((float) r->line_thickness) * scale + 1.0f), 0.0f); 515 | #if RAYLIB_VERSION_MAJOR >= 5 && RAYLIB_VERSION_MINOR == 0 516 | DrawRectangleRoundedLines(rect, roundness, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, (float)r->line_thickness * scale, color); 517 | #else 518 | DrawRectangleRoundedLinesEx(rect, roundness, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, (float)r->line_thickness * scale, color); 519 | #endif 520 | } 521 | else { 522 | DrawRectangleLinesEx(rect, r->line_thickness * scale, color); 523 | } 524 | } break; 525 | 526 | case NK_COMMAND_RECT_FILLED: { 527 | const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; 528 | Color color = ColorFromNuklear(r->color); 529 | Rectangle rect = CLITERAL(Rectangle) {(float)r->x * scale, (float)r->y * scale, (float)r->w * scale, (float)r->h * scale}; 530 | float roundness = (rect.width > rect.height) ? 531 | ((2 * r->rounding * scale)/rect.height) : ((2 * r->rounding * scale)/rect.width); 532 | roundness = NK_CLAMP(0.0f, roundness, 1.0f); 533 | if (roundness > 0.0f) { 534 | DrawRectangleRounded(rect, roundness, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color); 535 | } 536 | else { 537 | DrawRectangleRec(rect, color); 538 | } 539 | } break; 540 | 541 | case NK_COMMAND_RECT_MULTI_COLOR: { 542 | const struct nk_command_rect_multi_color* rectangle = (const struct nk_command_rect_multi_color *)cmd; 543 | Rectangle position = {(float)rectangle->x * scale, (float)rectangle->y * scale, (float)rectangle->w * scale, (float)rectangle->h * scale}; 544 | Color left = ColorFromNuklear(rectangle->left); 545 | Color top = ColorFromNuklear(rectangle->top); 546 | Color bottom = ColorFromNuklear(rectangle->bottom); 547 | Color right = ColorFromNuklear(rectangle->right); 548 | DrawRectangleGradientEx(position, left, bottom, right, top); 549 | } break; 550 | 551 | case NK_COMMAND_CIRCLE: { 552 | const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; 553 | Color color = ColorFromNuklear(c->color); 554 | for (unsigned short i = 0; i < c->line_thickness; i++) { 555 | DrawEllipseLines((int)(c->x * scale + c->w * scale / 2.0f), (int)(c->y * scale + c->h * scale / 2.0f), c->w * scale / 2.0f - (float)i / 2.0f, c->h * scale / 2.0f - (float)i / 2.0f, color); 556 | } 557 | } break; 558 | 559 | case NK_COMMAND_CIRCLE_FILLED: { 560 | const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; 561 | Color color = ColorFromNuklear(c->color); 562 | DrawEllipse((int)(c->x * scale + c->w * scale / 2.0f), (int)(c->y * scale + c->h * scale / 2.0f), (int)(c->w * scale / 2), (int)(c->h * scale / 2), color); 563 | } break; 564 | 565 | case NK_COMMAND_ARC: { 566 | const struct nk_command_arc *a = (const struct nk_command_arc*)cmd; 567 | Color color = ColorFromNuklear(a->color); 568 | Vector2 center = CLITERAL(Vector2) {(float)a->cx, (float)a->cy}; 569 | DrawRingLines(center, 0, a->r * scale, a->a[0] * RAD2DEG, a->a[1] * RAD2DEG, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color); 570 | } break; 571 | 572 | case NK_COMMAND_ARC_FILLED: { 573 | const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled*)cmd; 574 | Color color = ColorFromNuklear(a->color); 575 | Vector2 center = CLITERAL(Vector2) {(float)a->cx * scale, (float)a->cy * scale}; 576 | DrawRing(center, 0, a->r * scale, a->a[0] * RAD2DEG, a->a[1] * RAD2DEG, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color); 577 | } break; 578 | 579 | case NK_COMMAND_TRIANGLE: { 580 | const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; 581 | Color color = ColorFromNuklear(t->color); 582 | Vector2 point1 = CLITERAL(Vector2) {(float)t->b.x * scale, (float)t->b.y * scale}; 583 | Vector2 point2 = CLITERAL(Vector2) {(float)t->a.x * scale, (float)t->a.y * scale}; 584 | Vector2 point3 = CLITERAL(Vector2) {(float)t->c.x * scale, (float)t->c.y * scale}; 585 | 586 | // DrawLineEx(point1, point2, t->line_thickness * scale, color); 587 | // DrawLineEx(point2, point3, t->line_thickness * scale, color); 588 | // DrawLineEx(point3, point1, t->line_thickness * scale, color); 589 | // TODO: Add line thickness to DrawTriangleLines(), maybe via a DrawTriangleLinesEx()? 590 | DrawTriangleLines(point1, point2, point3, color); 591 | } break; 592 | 593 | case NK_COMMAND_TRIANGLE_FILLED: { 594 | const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; 595 | Color color = ColorFromNuklear(t->color); 596 | Vector2 point1 = CLITERAL(Vector2) {(float)t->b.x * scale, (float)t->b.y * scale}; 597 | Vector2 point2 = CLITERAL(Vector2) {(float)t->a.x * scale, (float)t->a.y * scale}; 598 | Vector2 point3 = CLITERAL(Vector2) {(float)t->c.x * scale, (float)t->c.y * scale}; 599 | DrawTriangle(point1, point2, point3, color); 600 | } break; 601 | 602 | case NK_COMMAND_POLYGON: { 603 | const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd; 604 | Color color = ColorFromNuklear(p->color); 605 | struct Vector2* points = (struct Vector2*)MemAlloc((unsigned int)((size_t)(p->point_count + 1) * sizeof(Vector2))); 606 | unsigned short i; 607 | for (i = 0; i < p->point_count; i++) { 608 | points[i].x = p->points[i].x * scale; 609 | points[i].y = p->points[i].y * scale; 610 | } 611 | points[p->point_count] = points[0]; 612 | DrawLineStrip(points, p->point_count + 1, color); 613 | MemFree(points); 614 | } break; 615 | 616 | case NK_COMMAND_POLYGON_FILLED: { 617 | // TODO: Implement NK_COMMAND_POLYGON_FILLED 618 | const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; 619 | Color color = ColorFromNuklear(p->color); 620 | struct Vector2* points = (struct Vector2*)MemAlloc((unsigned int)((size_t)(p->point_count + 1) * sizeof(Vector2))); 621 | for (unsigned short i = 0; i < p->point_count; i++) { 622 | points[i].x = p->points[i].x * scale; 623 | points[i].y = p->points[i].y * scale; 624 | } 625 | points[p->point_count] = points[0]; 626 | DrawLineStrip(points, p->point_count + 1, color); 627 | MemFree(points); 628 | } break; 629 | 630 | case NK_COMMAND_POLYLINE: { 631 | const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; 632 | Color color = ColorFromNuklear(p->color); 633 | for (unsigned short i = 0; i < p->point_count - 1; i++) { 634 | Vector2 start = {(float)p->points[i].x * scale, (float)p->points[i].y * scale}; 635 | Vector2 end = {(float)p->points[i + 1].x * scale, (float)p->points[i + 1].y * scale}; 636 | DrawLineEx(start, end, p->line_thickness * scale, color); 637 | } 638 | } break; 639 | 640 | case NK_COMMAND_TEXT: { 641 | const struct nk_command_text *text = (const struct nk_command_text*)cmd; 642 | Color color = ColorFromNuklear(text->foreground); 643 | float fontSize = text->font->height * scale; 644 | Font* font = (Font*)text->font->userdata.ptr; 645 | if (font != NULL) { 646 | Vector2 position = {(float)text->x * scale, (float)text->y * scale}; 647 | DrawTextEx(*font, (const char*)text->string, position, fontSize, fontSize * RAYLIB_NUKLEAR_FONT_SPACING_RATIO, color); 648 | } 649 | else { 650 | DrawText((const char*)text->string, (int)(text->x * scale), (int)(text->y * scale), (int)fontSize, color); 651 | } 652 | } break; 653 | 654 | case NK_COMMAND_IMAGE: { 655 | const struct nk_command_image *i = (const struct nk_command_image *)cmd; 656 | Texture texture = *(Texture*)i->img.handle.ptr; 657 | Rectangle source = CLITERAL(Rectangle) {(float)i->img.region[0], (float)i->img.region[1], (float)i->img.region[2], (float)i->img.region[3]}; 658 | Rectangle dest = CLITERAL(Rectangle) {(float)i->x * scale, (float)i->y * scale, (float)i->w * scale, (float)i->h * scale}; 659 | Vector2 origin = CLITERAL(Vector2) {0, 0}; 660 | Color tint = ColorFromNuklear(i->col); 661 | DrawTexturePro(texture, source, dest, origin, 0, tint); 662 | } break; 663 | 664 | case NK_COMMAND_CUSTOM: { 665 | TraceLog(LOG_WARNING, "NUKLEAR: Unverified custom callback implementation NK_COMMAND_CUSTOM"); 666 | const struct nk_command_custom *custom = (const struct nk_command_custom *)cmd; 667 | custom->callback(NULL, (short)(custom->x * scale), (short)(custom->y * scale), (unsigned short)(custom->w * scale), (unsigned short)(custom->h * scale), custom->callback_data); 668 | } break; 669 | 670 | default: { 671 | TraceLog(LOG_WARNING, "NUKLEAR: Missing implementation %i", cmd->type); 672 | } break; 673 | } 674 | } 675 | 676 | nk_clear(ctx); 677 | } 678 | 679 | struct nk_raylib_input_keyboard_check { 680 | int key; 681 | int input_key; 682 | bool modifier; 683 | }; 684 | 685 | /** 686 | * Update the Nuklear context for the keyboard input from raylib. 687 | * 688 | * @param ctx The nuklear context. 689 | * 690 | * @internal 691 | */ 692 | NK_API void 693 | nk_raylib_input_keyboard(struct nk_context * ctx) 694 | { 695 | bool control = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL); 696 | bool command = IsKeyDown(KEY_LEFT_SUPER); 697 | bool shift = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT); 698 | #define NK_RAYLIB_INPUT_KEYBOARD_CHECK_NUM 16 699 | struct nk_raylib_input_keyboard_check checks[NK_RAYLIB_INPUT_KEYBOARD_CHECK_NUM] = { 700 | (struct nk_raylib_input_keyboard_check) {KEY_DELETE, NK_KEY_DEL, true}, 701 | (struct nk_raylib_input_keyboard_check) {KEY_ENTER, NK_KEY_ENTER, true}, 702 | (struct nk_raylib_input_keyboard_check) {KEY_BACKSPACE, NK_KEY_BACKSPACE, true}, 703 | (struct nk_raylib_input_keyboard_check) {KEY_C, NK_KEY_COPY, (control || command)}, 704 | (struct nk_raylib_input_keyboard_check) {KEY_V, NK_KEY_PASTE, (control || command)}, 705 | (struct nk_raylib_input_keyboard_check) {KEY_B, NK_KEY_TEXT_LINE_START, (control || command)}, 706 | (struct nk_raylib_input_keyboard_check) {KEY_E, NK_KEY_TEXT_LINE_END, (control || command)}, 707 | (struct nk_raylib_input_keyboard_check) {KEY_Z, NK_KEY_TEXT_UNDO, (control || command)}, 708 | (struct nk_raylib_input_keyboard_check) {KEY_R, NK_KEY_TEXT_REDO, (control || command)}, 709 | (struct nk_raylib_input_keyboard_check) {KEY_A, NK_KEY_TEXT_SELECT_ALL, (control || command)}, 710 | (struct nk_raylib_input_keyboard_check) {KEY_LEFT, NK_KEY_TEXT_WORD_LEFT, (control || command)}, 711 | (struct nk_raylib_input_keyboard_check) {KEY_RIGHT, NK_KEY_TEXT_WORD_RIGHT, (control || command)}, 712 | (struct nk_raylib_input_keyboard_check) {KEY_RIGHT, NK_KEY_RIGHT, true}, 713 | (struct nk_raylib_input_keyboard_check) {KEY_LEFT, NK_KEY_LEFT, true}, 714 | (struct nk_raylib_input_keyboard_check) {KEY_UP, NK_KEY_UP, true}, 715 | (struct nk_raylib_input_keyboard_check) {KEY_DOWN, NK_KEY_DOWN, true} 716 | }; 717 | bool checked = false; 718 | for (int i = 0; i < NK_RAYLIB_INPUT_KEYBOARD_CHECK_NUM; i++) { 719 | struct nk_raylib_input_keyboard_check check = checks[i]; 720 | if (IsKeyDown(check.key) && check.modifier) { 721 | nk_input_key(ctx, (enum nk_keys)check.input_key, true); 722 | checked = true; 723 | } else { 724 | nk_input_key(ctx, (enum nk_keys)check.input_key, false); 725 | } 726 | } 727 | #undef NK_RAYLIB_INPUT_KEYBOARD_CHECK_NUM 728 | 729 | nk_input_key(ctx, NK_KEY_SHIFT, shift); 730 | 731 | if (checked) { 732 | return; 733 | } 734 | 735 | nk_input_key(ctx, NK_KEY_LEFT, IsKeyDown(KEY_LEFT)); 736 | nk_input_key(ctx, NK_KEY_RIGHT, IsKeyDown(KEY_RIGHT)); 737 | nk_input_key(ctx, NK_KEY_UP, IsKeyDown(KEY_UP)); 738 | nk_input_key(ctx, NK_KEY_DOWN, IsKeyDown(KEY_DOWN)); 739 | nk_input_key(ctx, NK_KEY_TEXT_START, IsKeyDown(KEY_HOME)); 740 | nk_input_key(ctx, NK_KEY_TEXT_END, IsKeyDown(KEY_END)); 741 | nk_input_key(ctx, NK_KEY_SCROLL_START, IsKeyDown(KEY_HOME) && control); 742 | nk_input_key(ctx, NK_KEY_SCROLL_END, IsKeyDown(KEY_END) && control); 743 | nk_input_key(ctx, NK_KEY_SCROLL_DOWN, IsKeyDown(KEY_PAGE_DOWN)); 744 | nk_input_key(ctx, NK_KEY_SCROLL_UP, IsKeyDown(KEY_PAGE_UP)); 745 | 746 | // Functions 747 | if (IsKeyPressed(KEY_TAB)) nk_input_unicode(ctx, 9); 748 | 749 | // Unicode 750 | int code; 751 | while ((code = GetCharPressed()) != 0) 752 | nk_input_unicode(ctx, (nk_rune)code); 753 | } 754 | 755 | /** 756 | * Update the Nuklear context for the mouse input from raylib. 757 | * 758 | * @param ctx The nuklear context. 759 | * 760 | * @internal 761 | */ 762 | NK_API void 763 | nk_raylib_input_mouse(struct nk_context * ctx) 764 | { 765 | const float scale = GetNuklearScaling(ctx); 766 | const int mouseX = (int)((float)GetMouseX() / scale); 767 | const int mouseY = (int)((float)GetMouseY() / scale); 768 | 769 | nk_input_motion(ctx, mouseX, mouseY); 770 | nk_input_button(ctx, NK_BUTTON_LEFT, mouseX, mouseY, IsMouseButtonDown(MOUSE_LEFT_BUTTON)); 771 | nk_input_button(ctx, NK_BUTTON_RIGHT, mouseX, mouseY, IsMouseButtonDown(MOUSE_RIGHT_BUTTON)); 772 | nk_input_button(ctx, NK_BUTTON_MIDDLE, mouseX, mouseY, IsMouseButtonDown(MOUSE_MIDDLE_BUTTON)); 773 | 774 | // Mouse Wheel 775 | float mouseWheel = GetMouseWheelMove(); 776 | if (mouseWheel != 0.0f) { 777 | struct nk_vec2 mouseWheelMove; 778 | mouseWheelMove.x = 0.0f; 779 | mouseWheelMove.y = mouseWheel; 780 | nk_input_scroll(ctx, mouseWheelMove); 781 | } 782 | } 783 | 784 | /** 785 | * Update the Nuklear context for raylib's state. 786 | * 787 | * @param ctx The nuklear context to act upon. 788 | */ 789 | NK_API void 790 | UpdateNuklear(struct nk_context * ctx) 791 | { 792 | UpdateNuklearEx(ctx, GetFrameTime()); 793 | } 794 | 795 | /** 796 | * Update the Nuklear context for raylib's state. 797 | * 798 | * @param ctx The nuklear context to act upon. 799 | * @param deltaTime Time in seconds since last frame. 800 | */ 801 | NK_API void 802 | UpdateNuklearEx(struct nk_context * ctx, float deltaTime) 803 | { 804 | // Update the time that has changed since last frame. 805 | ctx->delta_time_seconds = deltaTime; 806 | 807 | // Update the input state. 808 | nk_input_begin(ctx); 809 | { 810 | nk_raylib_input_mouse(ctx); 811 | nk_raylib_input_keyboard(ctx); 812 | } 813 | nk_input_end(ctx); 814 | } 815 | 816 | /** 817 | * Unload the given Nuklear context, along with all internal raylib textures. 818 | * 819 | * @param ctx The nuklear context. 820 | */ 821 | NK_API void 822 | UnloadNuklear(struct nk_context * ctx) 823 | { 824 | struct nk_user_font* userFont; 825 | 826 | // Skip unloading if it's not set. 827 | if (ctx == NULL) { 828 | return; 829 | } 830 | 831 | // Unload the font. 832 | userFont = (struct nk_user_font*)ctx->style.font; 833 | if (userFont != NULL) { 834 | // Clear the raylib Font object. 835 | void* fontPtr = userFont->userdata.ptr; 836 | if (fontPtr != NULL) { 837 | MemFree(fontPtr); 838 | } 839 | 840 | // Clear the user font. 841 | MemFree(userFont); 842 | ctx->style.font = NULL; 843 | } 844 | 845 | // Unload the custom user data. 846 | if (ctx->userdata.ptr != NULL) { 847 | MemFree(ctx->userdata.ptr); 848 | } 849 | 850 | // Unload the nuklear context. 851 | nk_free(ctx); 852 | MemFree(ctx); 853 | TraceLog(LOG_INFO, "NUKLEAR: Unloaded GUI"); 854 | } 855 | 856 | /** 857 | * Convert the given Nuklear rectangle to a raylib Rectangle. 858 | */ 859 | NK_API struct 860 | Rectangle RectangleFromNuklear(struct nk_context* ctx, struct nk_rect rect) 861 | { 862 | float scaling = GetNuklearScaling(ctx); 863 | Rectangle output; 864 | output.x = rect.x * scaling; 865 | output.y = rect.y * scaling; 866 | output.width = rect.w * scaling; 867 | output.height = rect.h * scaling; 868 | return output; 869 | } 870 | 871 | /** 872 | * Convert the given raylib Rectangle to a Nuklear rectangle. 873 | */ 874 | NK_API struct 875 | nk_rect RectangleToNuklear(struct nk_context* ctx, Rectangle rect) 876 | { 877 | float scaling = GetNuklearScaling(ctx); 878 | return nk_rect(rect.x / scaling, rect.y / scaling, rect.width / scaling, rect.height / scaling); 879 | } 880 | 881 | /** 882 | * Convert the given raylib texture to a Nuklear image 883 | */ 884 | NK_API struct nk_image 885 | TextureToNuklear(Texture tex) 886 | { 887 | // Declare the img to store data and allocate memory 888 | // For the texture 889 | struct nk_image img; 890 | struct Texture* stored_tex = (struct Texture*)MemAlloc(sizeof(Texture)); 891 | 892 | // Copy the data from the texture given into the new texture 893 | stored_tex->id = tex.id; 894 | stored_tex->width = tex.width; 895 | stored_tex->height = tex.height; 896 | stored_tex->mipmaps = tex.mipmaps; 897 | stored_tex->format = tex.format; 898 | 899 | // Initialize the nk_image struct 900 | img.handle.ptr = stored_tex; 901 | img.w = (nk_ushort)stored_tex->width; 902 | img.h = (nk_ushort)stored_tex->height; 903 | 904 | // Set the region so we can sub-select the image later. 905 | img.region[0] = (nk_ushort)0; 906 | img.region[1] = (nk_ushort)0; 907 | img.region[2] = img.w; 908 | img.region[3] = img.h; 909 | 910 | return img; 911 | } 912 | 913 | /** 914 | * Convert the given Nuklear image to a raylib Texture 915 | */ 916 | NK_API struct Texture 917 | TextureFromNuklear(struct nk_image img) 918 | { 919 | // Declare texture for storage 920 | // And get back the stored texture 921 | Texture tex; 922 | Texture* stored_tex = (Texture*)img.handle.ptr; 923 | 924 | // Copy the data from the stored texture to the texture 925 | tex.id = stored_tex->id; 926 | tex.width = stored_tex->width; 927 | tex.height = stored_tex->height; 928 | tex.mipmaps = stored_tex->mipmaps; 929 | tex.format = stored_tex->format; 930 | 931 | return tex; 932 | } 933 | 934 | /** 935 | * Load a Nuklear image directly 936 | * 937 | * @param path The path to the image 938 | */ 939 | NK_API struct nk_image 940 | LoadNuklearImage(const char* path) 941 | { 942 | return TextureToNuklear(LoadTexture(path)); 943 | } 944 | 945 | /** 946 | * Unload a loaded Nuklear image 947 | * 948 | * @param img The Nuklear image to unload 949 | */ 950 | NK_API void 951 | UnloadNuklearImage(struct nk_image img) 952 | { 953 | Texture tex = TextureFromNuklear(img); 954 | UnloadTexture(tex); 955 | CleanupNuklearImage(img); 956 | } 957 | 958 | /** 959 | * Cleans up memory used by a Nuklear image 960 | * Does not unload the image. 961 | * 962 | * @param img The Nuklear image to cleanup 963 | */ 964 | NK_API void 965 | CleanupNuklearImage(struct nk_image img) 966 | { 967 | MemFree(img.handle.ptr); 968 | } 969 | 970 | /** 971 | * Sets the scaling of the given Nuklear context. 972 | * 973 | * @param ctx The nuklear context. 974 | * @param scaling How much scale to apply to the graphical user interface. 975 | */ 976 | NK_API void 977 | SetNuklearScaling(struct nk_context * ctx, float scaling) 978 | { 979 | if (ctx == NULL) { 980 | return; 981 | } 982 | 983 | if (scaling <= 0.0f) { 984 | TraceLog(LOG_WARNING, "NUKLEAR: Cannot set scaling to be less than 0"); 985 | return; 986 | } 987 | 988 | struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr; 989 | if (userData != NULL) { 990 | userData->scaling = scaling; 991 | } 992 | } 993 | 994 | /** 995 | * Retrieves the scale value of the given Nuklear context. 996 | * 997 | * @return The scale value that had been set for the Nuklear context. 1.0f is the default scale value. 998 | */ 999 | NK_API float 1000 | GetNuklearScaling(struct nk_context * ctx) 1001 | { 1002 | if (ctx == NULL) { 1003 | return 1.0f; 1004 | } 1005 | 1006 | struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr; 1007 | if (userData != NULL) { 1008 | return userData->scaling; 1009 | } 1010 | 1011 | return 1.0f; 1012 | } 1013 | 1014 | #ifdef __cplusplus 1015 | } 1016 | #endif 1017 | 1018 | #endif // RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE 1019 | #endif // RAYLIB_NUKLEAR_IMPLEMENTATION 1020 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # raylib-nuklear-test 2 | add_executable(raylib-nuklear-test raylib-nuklear-test.c) 3 | target_compile_options(raylib-nuklear-test PRIVATE -Wall -Wextra -Wconversion -Wsign-conversion) 4 | target_link_libraries(raylib-nuklear-test PUBLIC 5 | raylib 6 | raylib_nuklear 7 | ) 8 | 9 | # Copy the resources 10 | file(GLOB resources resources/*) 11 | set(test_resources) 12 | list(APPEND test_resources ${resources}) 13 | file(COPY ${test_resources} DESTINATION "resources/") 14 | 15 | # Set up the test 16 | list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") 17 | add_test(NAME raylib-nuklear-test COMMAND raylib-nuklear-test) 18 | -------------------------------------------------------------------------------- /test/raylib-assert.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-assert - Assertion library for raylib. 4 | * https://github.com/robloach/raylib-assert 5 | * 6 | * Version: v3.0.0 7 | * 8 | * Copyright 2023 Rob Loach (@RobLoach) 9 | * 10 | * DEPENDENCIES: 11 | * raylib 5.5+ https://www.raylib.com 12 | * 13 | * LICENSE: zlib/libpng 14 | * 15 | * raylib-assert is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 16 | * BSD-like license that allows static linking with closed source software: 17 | * 18 | * This software is provided "as-is", without any express or implied warranty. In no event 19 | * will the authors be held liable for any damages arising from the use of this software. 20 | * 21 | * Permission is granted to anyone to use this software for any purpose, including commercial 22 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 23 | * 24 | * 1. The origin of this software must not be misrepresented; you must not claim that you 25 | * wrote the original software. If you use this software in a product, an acknowledgment 26 | * in the product documentation would be appreciated but is not required. 27 | * 28 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 29 | * as being the original software. 30 | * 31 | * 3. This notice may not be removed or altered from any source distribution. 32 | * 33 | **********************************************************************************************/ 34 | 35 | #ifndef RAYLIB_ASSERT_H 36 | #define RAYLIB_ASSERT_H 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | // How to report failed assertions 43 | #ifndef RAYLIB_ASSERT_LOG 44 | /** 45 | * The Trace Log Level used to report to TraceLog() on failed assertions. Defaults to LOG_FATAL. 46 | * 47 | * @example 48 | * #define RAYLIB_ASSERT_LOG LOG_WARNING 49 | * 50 | * @see TraceLogLevel 51 | */ 52 | #define RAYLIB_ASSERT_LOG LOG_FATAL 53 | #endif 54 | 55 | // Define NDEBUG or RAYLIB_ASSERT_NDEBUG to skip assertions 56 | #ifdef NDEBUG 57 | #ifndef RAYLIB_ASSERT_NDEBUG 58 | #define RAYLIB_ASSERT_NDEBUG 59 | #endif 60 | #endif 61 | 62 | #ifndef RAYLIB_ASSERT_TRACELOG 63 | /** 64 | * The TraceLog() function to use. 65 | * 66 | * @see TraceLog() 67 | */ 68 | #define RAYLIB_ASSERT_TRACELOG TraceLog 69 | #endif 70 | 71 | #ifndef RAYLIB_ASSERT_TEXTFORMAT 72 | /** 73 | * The TextFormat() function to use when formating text. 74 | * 75 | * @see TextFormat() 76 | */ 77 | #define RAYLIB_ASSERT_TEXTFORMAT TextFormat 78 | #endif 79 | 80 | // Variadic Arguments 81 | #define RAYLIB_ASSERT_CAT( A, B ) A ## B 82 | #define RAYLIB_ASSERT_SELECT( NAME, NUM ) RAYLIB_ASSERT_CAT( NAME ## _, NUM ) 83 | #define RAYLIB_ASSERT_GET_COUNT( _1, _2, _3, _4, _5, _6, _7, RAYLIB_ASSERT_COUNT, ... ) RAYLIB_ASSERT_COUNT 84 | #define RAYLIB_ASSERT_VA_SIZE( ... ) RAYLIB_ASSERT_GET_COUNT( __VA_ARGS__, 7, 6, 5, 4, 3, 2, 1 ) 85 | #define RAYLIB_ASSERT_VA_SELECT( NAME, ... ) RAYLIB_ASSERT_SELECT( NAME, RAYLIB_ASSERT_VA_SIZE(__VA_ARGS__) )(__VA_ARGS__) 86 | 87 | /** 88 | * Assert whether the given condition is true. 89 | * 90 | * @param condition The condition that is expected to be true. 91 | * @param message (Optional) The message to provide on failed assertions. 92 | * @param p1 (Optional) The first parameter in the message. 93 | * @param p2 (Optional) The second parameter in the message. 94 | * @param p3 (Optional) The third parameter in the message. 95 | * @param p4 (Optional) The fourth parameter in the message. 96 | * @param p5 (Optional) The fifth parameter in the message. 97 | */ 98 | #define Assert(...) RAYLIB_ASSERT_VA_SELECT(Assert, __VA_ARGS__) 99 | 100 | /** 101 | * Assert whether the two given parameters are equal. 102 | * 103 | * @param actual The actual value. 104 | * @param expected The expected value. 105 | * @param message (Optional) The message to provide on failed assertions. 106 | * @param p1 (Optional) The first parameter in the message. 107 | * @param p2 (Optional) The second parameter in the message. 108 | * @param p3 (Optional) The third parameter in the message. 109 | * @param p4 (Optional) The fourth parameter in the message. 110 | */ 111 | #define AssertEqual(...) RAYLIB_ASSERT_VA_SELECT(AssertEqual, __VA_ARGS__) 112 | 113 | /** 114 | * Assert whether the given condition is false. 115 | * 116 | * @param condition The condition that is expected to be false. 117 | * @param message (Optional) The message to provide on failed assertions. 118 | * @param p1 (Optional) The first parameter in the message. 119 | * @param p2 (Optional) The second parameter in the message. 120 | * @param p3 (Optional) The third parameter in the message. 121 | * @param p4 (Optional) The fourth parameter in the message. 122 | * @param p5 (Optional) The fifth parameter in the message. 123 | */ 124 | #define AssertNot(...) RAYLIB_ASSERT_VA_SELECT(AssertNot, __VA_ARGS__) 125 | 126 | /** 127 | * Assert whether the two given parameters are not equal. 128 | * 129 | * @param actual The actual value. 130 | * @param notexpected The expected value that shouldn't equal the actual value. 131 | * @param message (Optional) The message to provide on failed assertions. 132 | * @param p1 (Optional) The first parameter in the message. 133 | * @param p2 (Optional) The second parameter in the message. 134 | * @param p3 (Optional) The third parameter in the message. 135 | * @param p4 (Optional) The fourth parameter in the message. 136 | */ 137 | #define AssertNotEqual(...) RAYLIB_ASSERT_VA_SELECT(AssertNotEqual, __VA_ARGS__) 138 | 139 | /** 140 | * Sets a failed assertion, with the given message. 141 | * 142 | * @param message (Optional) The message to provide for the failed assertion. 143 | * @param p1 (Optional) The first parameter in the message. 144 | * @param p2 (Optional) The second parameter in the message. 145 | * @param p3 (Optional) The third parameter in the message. 146 | * @param p4 (Optional) The fourth parameter in the message. 147 | * @param p5 (Optional) The fifth parameter in the message. 148 | * @param p6 (Optional) The sixth parameter in the message. 149 | */ 150 | #define AssertFail(...) RAYLIB_ASSERT_VA_SELECT(AssertFail, __VA_ARGS__) 151 | 152 | /** 153 | * Assert whether an image is loaded. 154 | * 155 | * @param image The image to check for valid data. 156 | * @param message (Optional) The message to provide on failed assertions. 157 | * @param p1 (Optional) The first parameter in the message. 158 | * @param p2 (Optional) The second parameter in the message. 159 | * @param p3 (Optional) The third parameter in the message. 160 | * @param p4 (Optional) The fourth parameter in the message. 161 | * @param p5 (Optional) The fifth parameter in the message. 162 | */ 163 | #define AssertImage(...) RAYLIB_ASSERT_VA_SELECT(AssertImage, __VA_ARGS__) 164 | 165 | /** 166 | * Assert whether two images are the same. 167 | * 168 | * @param image1 The first image to check is equal to the second. 169 | * @param image2 The second image to check is equal to the first. 170 | * @param message (Optional) The message to provide on failed assertions. 171 | * @param p1 (Optional) The first parameter in the message. 172 | * @param p2 (Optional) The second parameter in the message. 173 | * @param p3 (Optional) The third parameter in the message. 174 | * @param p4 (Optional) The fourth parameter in the message. 175 | */ 176 | #define AssertImageSame(...) RAYLIB_ASSERT_VA_SELECT(AssertImageSame, __VA_ARGS__) 177 | 178 | /** 179 | * Assert whether two colors are the same. 180 | * 181 | * @param color1 The first color to check. 182 | * @param color2 The second color to check. 183 | * @param message (Optional) The message to provide on failed assertions. 184 | * @param p1 (Optional) The first parameter in the message. 185 | * @param p2 (Optional) The second parameter in the message. 186 | * @param p3 (Optional) The third parameter in the message. 187 | * @param p4 (Optional) The fourth parameter in the message. 188 | */ 189 | #define AssertColorSame(...) RAYLIB_ASSERT_VA_SELECT(AssertColorSame, __VA_ARGS__) 190 | 191 | /** 192 | * Assert whether two Vector2s are the same. 193 | * 194 | * @param vector1 The first Vector2 to check. 195 | * @param vector2 The second Vector2 to check. 196 | * @param message (Optional) The message to provide on failed assertions. 197 | * @param p1 (Optional) The first parameter in the message. 198 | * @param p2 (Optional) The second parameter in the message. 199 | * @param p3 (Optional) The third parameter in the message. 200 | * @param p4 (Optional) The fourth parameter in the message. 201 | */ 202 | #define AssertVector2Same(...) RAYLIB_ASSERT_VA_SELECT(AssertVector2Same, __VA_ARGS__) 203 | 204 | /** 205 | * Assert whether two Vector3s are the same. 206 | * 207 | * @param vector1 The first Vector3 to check. 208 | * @param vector2 The second Vector3 to check. 209 | * @param message (Optional) The message to provide on failed assertions. 210 | * @param p1 (Optional) The first parameter in the message. 211 | * @param p2 (Optional) The second parameter in the message. 212 | * @param p3 (Optional) The third parameter in the message. 213 | * @param p4 (Optional) The fourth parameter in the message. 214 | */ 215 | #define AssertVector3Same(...) RAYLIB_ASSERT_VA_SELECT(AssertVector3Same, __VA_ARGS__) 216 | 217 | // Assert() 218 | #ifdef RAYLIB_ASSERT_NDEBUG 219 | #define Assert_0() 220 | #define Assert_1(condition) 221 | #define Assert_2(condition, message) 222 | #define Assert_3(condition, message, p1) 223 | #define Assert_4(condition, message, p1, p2) 224 | #define Assert_5(condition, message, p1, p2, p3) 225 | #define Assert_6(condition, message, p1, p2, p3, p4) 226 | #define Assert_7(condition, message, p1, p2, p3, p4, p5) 227 | #else 228 | #define Assert_0() AssertFail_1("No condition provided for Assert()") 229 | #define Assert_1(condition) Assert_2(condition, #condition) 230 | #define Assert_2(condition, message) do { if (!((bool)(condition))) { RAYLIB_ASSERT_TRACELOG(RAYLIB_ASSERT_LOG, "ASSERT: %s (%s:%i)", message, __FILE__, __LINE__); } } while(0) 231 | #define Assert_3(condition, message, p1) Assert_2(condition, RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 232 | #define Assert_4(condition, message, p1, p2) Assert_2(condition, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 233 | #define Assert_5(condition, message, p1, p2, p3) Assert_2(condition, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 234 | #define Assert_6(condition, message, p1, p2, p3, p4) Assert_2(condition, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 235 | #define Assert_7(condition, message, p1, p2, p3, p4, p5) Assert_2(condition, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4, p5)) 236 | #endif 237 | 238 | // AssertEqual() 239 | #define AssertEqual_0() AssertFail_1("No condition provided for AssertEqual()") 240 | #define AssertEqual_1(condition) Assert_2(condition, #condition) 241 | #define AssertEqual_2(actual, expected) Assert_4((actual) == (expected), "AssertEqual(%s, %s) - Provided arguments are not equal", #actual, #expected) 242 | #define AssertEqual_3(actual, expected, message) Assert_2((actual) == (expected), message) 243 | #define AssertEqual_4(actual, expected, message, p1) Assert_3((actual) == (expected), message, p1) 244 | #define AssertEqual_5(actual, expected, message, p1, p2) Assert_4((actual) == (expected), message, p1, p2) 245 | #define AssertEqual_6(actual, expected, message, p1, p2, p3) Assert_5((actual) == (expected), message, p1, p2, p3) 246 | #define AssertEqual_7(actual, expected, message, p1, p2, p3, p4) Assert_6((actual) == (expected), message, p1, p2, p3, p4) 247 | 248 | // AssertNotEqual() 249 | #define AssertNotEqual_0() AssertFail_1("No condition provided for AssertNotEqual()") 250 | #define AssertNotEqual_1(condition) AssertNot_2(condition, #condition) 251 | #define AssertNotEqual_2(actual, expected) Assert_4((actual) != (expected), "AssertNotEqual(%s, %s) - Provided arguments are equal", #actual, #expected) 252 | #define AssertNotEqual_3(actual, expected, message) Assert_2((actual) != (expected), message) 253 | #define AssertNotEqual_4(actual, expected, message, p1) Assert_3((actual) != (expected), message, p1) 254 | #define AssertNotEqual_5(actual, expected, message, p1, p2) Assert_4((actual) != (expected), message, p1, p2) 255 | #define AssertNotEqual_6(actual, expected, message, p1, p2, p3) Assert_5((actual) != (expected), message, p1, p2, p3) 256 | #define AssertNotEqual_7(actual, expected, message, p1, p2, p3, p4) Assert_6((actual) != (expected), message, p1, p2, p3, p4) 257 | 258 | // AssertNot() 259 | #define AssertNot_0() AssertFail_1("No condition provided for AssertNot()") 260 | #define AssertNot_1(condition) Assert_2(!(bool)(condition), #condition) 261 | #define AssertNot_2(condition, message) Assert_2(!(bool)(condition), message) 262 | #define AssertNot_3(condition, message, p1) Assert_3(!(bool)(condition), message, p1) 263 | #define AssertNot_4(condition, message, p1, p2) Assert_4(!(bool)(condition), message, p1, p2) 264 | #define AssertNot_5(condition, message, p1, p2, p3) Assert_5(!(bool)(condition), message, p1, p2, p3) 265 | #define AssertNot_6(condition, message, p1, p2, p3, p4) Assert_6(!(bool)(condition), message, p1, p2, p3, p4) 266 | #define AssertNot_7(condition, message, p1, p2, p3, p4, p5) Assert_7(!(bool)(condition), message, p1, p2, p3, p4, p5) 267 | 268 | // AssertFail() 269 | #ifdef RAYLIB_ASSERT_NDEBUG 270 | #define AssertFail_0() 271 | #define AssertFail_1(message) 272 | #define AssertFail_2(message, p1) 273 | #define AssertFail_3(message, p1, p2) 274 | #define AssertFail_4(message, p1, p2, p3) 275 | #define AssertFail_5(message, p1, p2, p3, p4) 276 | #define AssertFail_6(message, p1, p2, p3, p4, p5) 277 | #define AssertFail_7(message, p1, p2, p3, p4, p5, p6) 278 | #else 279 | #define AssertFail_0() RAYLIB_ASSERT_TRACELOG(RAYLIB_ASSERT_LOG, "ASSERT: AssertFail() (%s:%i)", __FILE__, __LINE__) 280 | #define AssertFail_1(message) RAYLIB_ASSERT_TRACELOG(RAYLIB_ASSERT_LOG, "ASSERT: %s (%s:%i)", message, __FILE__, __LINE__) 281 | #define AssertFail_2(message, p1) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 282 | #define AssertFail_3(message, p1, p2) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 283 | #define AssertFail_4(message, p1, p2, p3) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 284 | #define AssertFail_5(message, p1, p2, p3, p4) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 285 | #define AssertFail_6(message, p1, p2, p3, p4, p5) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4, p5)) 286 | #define AssertFail_7(message, p1, p2, p3, p4, p5, p6) AssertFail_1(RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4, p5, p6)) 287 | #endif 288 | 289 | // AssertImage() 290 | #define AssertImage_0() AssertFail_1("No image provided for AssertImage()") 291 | #define AssertImage_1(image) Assert_3(IsImageValid(image), "AssertImage(%s) - Image not loaded", #image) 292 | #define AssertImage_2(image, message) Assert_2(IsImageValid(image), message) 293 | #define AssertImage_3(image, message, p1) Assert_3(IsImageValid(image), message, p1) 294 | #define AssertImage_4(image, message, p1, p2) Assert_4(IsImageValid(image), message, p1, p2) 295 | #define AssertImage_5(image, message, p1, p2, p3) Assert_5(IsImageValid(image), message, p1, p2, p3) 296 | #define AssertImage_6(image, message, p1, p2, p3, p4) Assert_6(IsImageValid(image), message, p1, p2, p3, p4) 297 | 298 | // AssertTexture() 299 | #define AssertTexture_0() AssertFail_1("No texture provided for AssertTexture()") 300 | #define AssertTexture_1(texture) Assert_3(IsTextureValid(texture), "AssertTexture(%s) - Texture not loaded", #texture) 301 | #define AssertTexture_2(texture, message) Assert_2(IsTextureValid(texture), message) 302 | #define AssertTexture_3(texture, message, p1) Assert_3(IsTextureValid(texture), message, p1) 303 | #define AssertTexture_4(texture, message, p1, p2) Assert_4(IsTextureValid(texture), message, p1, p2) 304 | #define AssertTexture_5(texture, message, p1, p2, p3) Assert_5(IsTextureValid(texture), message, p1, p2, p3) 305 | #define AssertTexture_6(texture, message, p1, p2, p3, p4) Assert_6(IsTextureValid(texture), message, p1, p2, p3, p4) 306 | 307 | // AssertImageSame() 308 | #ifdef RAYLIB_ASSERT_NDEBUG 309 | #define AssertImageSame_0() 310 | #define AssertImageSame_1(image) 311 | #define AssertImageSame_2(image1, image2) 312 | #define AssertImageSame_3(image1, image2, message) 313 | #define AssertImageSame_4(image1, image2, message, p1) 314 | #define AssertImageSame_5(image1, image2, message, p1, p2) 315 | #define AssertImageSame_6(image1, image2, message, p1, p2, p3) 316 | #define AssertImageSame_7(image1, image2, message, p1, p2, p3, p4) 317 | #else 318 | #define AssertImageSame_0() AssertFail_1("AssertImageSame(): No images provided to AssertImageSame(), expected 2") 319 | #define AssertImageSame_1(image) AssertFail_1("Only one image provided for AssertImageSame()") 320 | #define AssertImageSame_2(image1, image2) AssertImageSame_5(image1, image2, "AssertImageSame(%s, %s) - Images do not match", #image1, #image2) 321 | #define AssertImageSame_3(image1, image2, message) do { \ 322 | if (image1.width != image2.width || image1.height != image2.height || image1.format != image2.format) { \ 323 | AssertFail_1(message); \ 324 | break; \ 325 | } \ 326 | Color* colors1 = LoadImageColors(image1); \ 327 | Color* colors2 = LoadImageColors(image2); \ 328 | bool failure = false; \ 329 | for (int i = 0; i < image1.width * image1.height; i++) { \ 330 | Color color1 = colors1[i]; \ 331 | Color color2 = colors2[i]; \ 332 | if (color1.r != color2.r || color1.g != color2.g || color1.b != color2.b || color1.a != color2.a) { \ 333 | failure = true; \ 334 | break; \ 335 | } \ 336 | } \ 337 | UnloadImageColors(colors1); \ 338 | UnloadImageColors(colors2); \ 339 | if (failure) { \ 340 | AssertFail_1(message); \ 341 | } \ 342 | } while(0) 343 | #define AssertImageSame_4(image1, image2, message, p1) AssertImageSame_3(image1, image2, RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 344 | #define AssertImageSame_5(image1, image2, message, p1, p2) AssertImageSame_3(image1, image2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 345 | #define AssertImageSame_6(image1, image2, message, p1, p2, p3) AssertImageSame_3(image1, image2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 346 | #define AssertImageSame_7(image1, image2, message, p1, p2, p3, p4) AssertImageSame_3(image1, image2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 347 | #endif 348 | 349 | // AssertColorSame() 350 | #ifdef RAYLIB_ASSERT_NDEBUG 351 | #define AssertColorSame_0() 352 | #define AssertColorSame_1(color) 353 | #define AssertColorSame_2(color1, color2) 354 | #define AssertColorSame_3(color1, color2, message) 355 | #define AssertColorSame_4(color1, color2, message, p1) 356 | #define AssertColorSame_5(color1, color2, message, p1, p2) 357 | #define AssertColorSame_6(color1, color2, message, p1, p2, p3) 358 | #define AssertColorSame_7(color1, color2, message, p1, p2, p3, p4) 359 | #else 360 | #define AssertColorSame_0() AssertFail_1("Colors not provided to AssertColorSame()") 361 | #define AssertColorSame_1(color) AssertFail_1("Expected two colors for AssertColorSame()") 362 | #define AssertColorSame_2(color1, color2) AssertColorSame_5(color1, color2, "AssertColorSame(%s, %s) - Colors do not match", #color1, #color2) 363 | #define AssertColorSame_3(color1, color2, message) do { \ 364 | if (color1.r != color2.r || color1.g != color2.g || color1.b != color2.b || color1.a != color2.a) { \ 365 | AssertFail_1(message); \ 366 | }\ 367 | } while (0) 368 | #define AssertColorSame_4(color1, color2, message, p1) AssertColorSame_3(color1, color2, RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 369 | #define AssertColorSame_5(color1, color2, message, p1, p2) AssertColorSame_3(color1, color2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 370 | #define AssertColorSame_6(color1, color2, message, p1, p2, p3) AssertColorSame_3(color1, color2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 371 | #define AssertColorSame_7(color1, color2, message, p1, p2, p3, p4) AssertColorSame_3(color1, color2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 372 | #endif 373 | 374 | // AssertVector2Same() 375 | #ifdef RAYLIB_ASSERT_NDEBUG 376 | #define AssertVector2Same_0() 377 | #define AssertVector2Same_1(vector) 378 | #define AssertVector2Same_2(vector1, vector2) 379 | #define AssertVector2Same_3(vector1, vector2, message) 380 | #define AssertVector2Same_4(vector1, vector2, message, p1) 381 | #define AssertVector2Same_5(vector1, vector2, message, p1, p2) 382 | #define AssertVector2Same_6(vector1, vector2, message, p1, p2, p3) 383 | #define AssertVector2Same_7(vector1, vector2, message, p1, p2, p3, p4) 384 | #else 385 | #define AssertVector2Same_0() AssertFail_1("Vectors not provided to AssertVector2Same()") 386 | #define AssertVector2Same_1(vector) AssertFail_1("Expected two vectors for AssertVector2Same()") 387 | #define AssertVector2Same_2(vector1, vector2) AssertVector2Same_5(vector1, vector2, "AssertVector2Same(%s, %s) - vectors do not match", #vector1, #vector2) 388 | #define AssertVector2Same_3(vector1, vector2, message) do { \ 389 | if (vector1.x != vector2.x || vector1.y != vector2.y) { \ 390 | AssertFail_1(message); \ 391 | }\ 392 | } while (0) 393 | #define AssertVector2Same_4(vector1, vector2, message, p1) AssertVector2Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 394 | #define AssertVector2Same_5(vector1, vector2, message, p1, p2) AssertVector2Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 395 | #define AssertVector2Same_6(vector1, vector2, message, p1, p2, p3) AssertVector2Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 396 | #define AssertVector2Same_7(vector1, vector2, message, p1, p2, p3, p4) AssertVector2Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 397 | #endif 398 | 399 | // AssertVector3Same() 400 | #ifdef RAYLIB_ASSERT_NDEBUG 401 | #define AssertVector3Same_0() 402 | #define AssertVector3Same_1(vector) 403 | #define AssertVector3Same_2(vector1, vector2) 404 | #define AssertVector3Same_3(vector1, vector2, message) 405 | #define AssertVector3Same_4(vector1, vector2, message, p1) 406 | #define AssertVector3Same_5(vector1, vector2, message, p1, p2) 407 | #define AssertVector3Same_6(vector1, vector2, message, p1, p2, p3) 408 | #define AssertVector3Same_7(vector1, vector2, message, p1, p2, p3, p4) 409 | #else 410 | #define AssertVector3Same_0() AssertFail_1("Vectors not provided to AssertVector2Same()") 411 | #define AssertVector3Same_1(vector) AssertFail_1("Expected two vectors for AssertVector2Same()") 412 | #define AssertVector3Same_2(vector1, vector2) AssertVector3Same_5(vector1, vector2, "AssertVector2Same(%s, %s) - vectors do not match", #vector1, #vector2) 413 | #define AssertVector3Same_3(vector1, vector2, message) do { \ 414 | if (vector1.x != vector2.x || vector1.y != vector2.y || vector1.z != vector2.z) { \ 415 | AssertFail_1(message); \ 416 | }\ 417 | } while (0) 418 | #define AssertVector3Same_4(vector1, vector2, message, p1) AssertVector3Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1)) 419 | #define AssertVector3Same_5(vector1, vector2, message, p1, p2) AssertVector3Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2)) 420 | #define AssertVector3Same_6(vector1, vector2, message, p1, p2, p3) AssertVector3Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3)) 421 | #define AssertVector3Same_7(vector1, vector2, message, p1, p2, p3, p4) AssertVector3Same_3(vector1, vector2, RAYLIB_ASSERT_TEXTFORMAT(message, p1, p2, p3, p4)) 422 | #endif 423 | 424 | #ifdef __cplusplus 425 | } 426 | #endif 427 | 428 | #endif // RAYLIB_ASSERT_H 429 | -------------------------------------------------------------------------------- /test/raylib-nuklear-test.c: -------------------------------------------------------------------------------- 1 | #include "raylib.h" 2 | 3 | #define RAYLIB_NUKLEAR_IMPLEMENTATION 4 | #include "raylib-nuklear.h" 5 | 6 | #include "raylib-assert.h" 7 | 8 | int main(int argc, char *argv[]) { 9 | // Initialization 10 | SetTraceLogLevel(LOG_ALL); 11 | TraceLog(LOG_INFO, "================================"); 12 | TraceLog(LOG_INFO, "raylib-nuklear-test"); 13 | TraceLog(LOG_INFO, "================================"); 14 | 15 | InitWindow(640, 480, "raylib-nuklear-tests"); 16 | Assert(IsWindowReady()); 17 | 18 | // Make sure we're running in the correct directory. 19 | Assert(argc > 0); 20 | const char* dir = GetDirectoryPath(argv[0]); 21 | Assert(ChangeDirectory(dir)); 22 | 23 | // InitNuklear() 24 | struct nk_context *ctx = InitNuklear(10); 25 | Assert(ctx); 26 | 27 | // Image 28 | struct nk_image image = LoadNuklearImage("resources/test-image.png"); 29 | Assert(image.handle.ptr); 30 | Texture texture = TextureFromNuklear(image); 31 | Assert(texture.width > 0); 32 | 33 | // UpdateNuklear() 34 | UpdateNuklear(ctx); 35 | 36 | // UpdateNuklearEx() 37 | UpdateNuklearEx(ctx, 1.0f / 60.0f); 38 | 39 | // Nuklear GUI Code 40 | // https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window 41 | if (nk_begin(ctx, "Nuklear", nk_rect(50, 50, 400, 400), 42 | NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { 43 | nk_button_label(ctx, "Button"); 44 | nk_layout_row_static(ctx, 256, 256, 1); 45 | nk_image(ctx, image); 46 | } 47 | nk_end(ctx); 48 | 49 | // Render 50 | BeginDrawing(); 51 | ClearBackground(RAYWHITE); 52 | 53 | // DrawNuklear() 54 | DrawNuklear(ctx); 55 | EndDrawing(); 56 | 57 | // Save a screenshot for debugging. 58 | TakeScreenshot("raylib-nuklear-test.png"); 59 | 60 | // UnloadNuklearImage() 61 | UnloadNuklearImage(image); 62 | 63 | // UnloadNuklear() 64 | UnloadNuklear(ctx); 65 | 66 | // InitNuklearEx() 67 | { 68 | Font font = LoadFont("resources/anonymous_pro_bold.ttf"); 69 | ctx = InitNuklearEx(font, 25.0f); 70 | Assert(ctx); 71 | UnloadNuklear(ctx); 72 | UnloadFont(font); 73 | } 74 | 75 | // RectangleFromNuklear() 76 | { 77 | ctx = NULL; 78 | struct nk_rect rect = nk_rect(10, 20, 30, 40); 79 | Rectangle rectangle = RectangleFromNuklear(ctx, rect); 80 | AssertEqual(rect.x, rectangle.x); 81 | AssertEqual(rect.y, rectangle.y); 82 | AssertEqual(rect.w, rectangle.width); 83 | AssertEqual(rect.h, rectangle.height); 84 | } 85 | 86 | // RectangleFromNuklear(), RectangleToNuklear(), with scaling 87 | { 88 | struct nk_rect rect = nk_rect(10, 20, 30, 40); 89 | ctx = InitNuklear(10); 90 | SetNuklearScaling(ctx, 2.0f); 91 | float scaling = GetNuklearScaling(ctx); 92 | AssertEqual(scaling, 2.0f, "Scaling was incorrectly set."); 93 | Rectangle rectangle = RectangleFromNuklear(ctx, rect); 94 | AssertEqual(rect.x, rectangle.x / 2); 95 | AssertEqual(rect.y, rectangle.y / 2); 96 | AssertEqual(rect.w, rectangle.width / 2); 97 | AssertEqual(rect.h, rectangle.height / 2); 98 | 99 | rectangle = (Rectangle){20, 40, 60, 80}; 100 | rect = RectangleToNuklear(ctx, rectangle); 101 | AssertEqual(rect.x, rectangle.x / 2); 102 | AssertEqual(rect.y, rectangle.y / 2); 103 | AssertEqual(rect.w, rectangle.width / 2); 104 | AssertEqual(rect.h, rectangle.height / 2); 105 | 106 | UnloadNuklear(ctx); 107 | } 108 | 109 | CloseWindow(); 110 | TraceLog(LOG_INFO, "================================"); 111 | TraceLog(LOG_INFO, "raylib-nuklear tests succesful"); 112 | TraceLog(LOG_INFO, "================================"); 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /test/resources/anonymous_pro_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobLoach/raylib-nuklear/d2bd2b7b3cef4831c0a57ee1b0e11a76a9fe1c19/test/resources/anonymous_pro_bold.ttf -------------------------------------------------------------------------------- /test/resources/test-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobLoach/raylib-nuklear/d2bd2b7b3cef4831c0a57ee1b0e11a76a9fe1c19/test/resources/test-image.png --------------------------------------------------------------------------------