nuklear dev ui + asset inspector tool

efd/v1
Dominik Madarász 2023-01-15 16:59:33 +01:00
parent d00ce4ec80
commit 72005402cf
50 changed files with 33056 additions and 772 deletions

View File

@ -29,8 +29,8 @@ add_library(eco2d-foundation STATIC
src/gen/texgen_fallback.c
src/debug/debug_ui.c
src/debug/debug_draw.c
src/dev/debug_ui.c
src/dev/debug_draw.c
src/utils/options.c
src/utils/compress.c
@ -51,6 +51,6 @@ add_library(eco2d-foundation STATIC
target_compile_definitions(eco2d-foundation PRIVATE CLIENT)
include_directories(src ../modules ../../art/gen)
target_link_libraries(eco2d-foundation raylib cwpack flecs-bundle vendors-bundle)
target_link_libraries(eco2d-foundation raylib raylib_nuklear cwpack flecs-bundle vendors-bundle)
link_system_libs(eco2d-foundation)

View File

@ -1,4 +1,4 @@
#include "debug/debug_draw.h"
#include "dev/debug_draw.h"
#include "core/game.h"
static debug_draw_queue draw_queue = {0};

View File

@ -1,4 +1,4 @@
#include "debug/debug_replay.h"
#include "dev/debug_replay.h"
#include "core/camera.h"
#include "models/entity.h"

View File

@ -1,5 +1,5 @@
#include "debug/debug_ui.h"
#include "debug/debug_draw.h"
#include "dev/debug_ui.h"
#include "dev/debug_draw.h"
#include "raylib.h"
#include "models/prefabs/vehicle.h"
#include "core/camera.h"
@ -9,6 +9,12 @@
#include "models/components.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#define NK_INCLUDE_STANDARD_VARARGS
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
typedef enum {
DITEM_RAW,
DITEM_GAP,
@ -16,7 +22,9 @@ typedef enum {
DITEM_BUTTON,
DITEM_SLIDER,
DITEM_LIST,
DITEM_TOOL,
DITEM_COND,
DITEM_END,
DITEM_FORCE_UINT8 = UINT8_MAX
@ -42,6 +50,7 @@ static uint8_t is_handle_ctrl_held;
static float debug_xpos = DBG_START_XPOS;
static float debug_ypos = DBG_START_YPOS;
static zpl_u16 sel_item_id = 0;
static struct nk_context *nk_ctx = 0;
typedef enum {
L_NONE = 0,
@ -72,6 +81,11 @@ typedef struct debug_item {
void (*on_change)(float);
} slider;
struct {
uint8_t is_open;
void (*on_draw)(void);
} tool;
void (*on_click)(void);
uint8_t (*on_success)(void);
@ -83,10 +97,11 @@ typedef struct debug_item {
static void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
static int UIMeasureText(const char *text, int fontSize);
#include "debug/debug_replay.c"
#include "dev/debug_replay.c"
#include "debug/debug_ui_actions.c"
#include "debug/debug_ui_widgets.c"
#include "dev/debug_ui_actions.c"
#include "dev/debug_ui_widgets.c"
#include "dev/debug_ui_tools.c"
static debug_item items[] = {
{
@ -246,7 +261,18 @@ static debug_item items[] = {
},
.is_collapsed = 1
}
},
},
{
.kind = DITEM_LIST,
.name = "tools",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TOOL, .name = "asset inspector", .tool = { .is_open = 0, .on_draw = ToolAssetInspector } },
{ .kind = DITEM_END },
},
.is_collapsed = 0
}
},
#if !defined(PLATFORM_WEB)
{
.kind = DITEM_BUTTON,
@ -349,6 +375,25 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
ypos += DBG_FONT_SPACING;
}break;
case DITEM_TOOL: {
char const *text = TextFormat("> %s", it->name);
if (it->name_width == 0) {
it->name_width = (float)UIMeasureText(text, DBG_FONT_SIZE);
}
Color color = RAYWHITE;
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->tool.is_open ^= 1;
}
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
ypos = res.y;
if (it->tool.is_open) {
if (is_shadow_rendered) break;
it->tool.on_draw();
}
} break;
default: {
}break;
@ -366,8 +411,13 @@ void debug_draw(void) {
if (!first_run) {
first_run = 1;
ActSpawnItemNext();
// Initialize Nuklear ctx
nk_ctx = InitNuklear(10);
}
UpdateNuklear(nk_ctx);
float xpos = debug_xpos;
float ypos = debug_ypos;
@ -412,6 +462,8 @@ void debug_draw(void) {
debug_draw_list(items, xpos+DBG_SHADOW_OFFSET_XPOS, ypos+DBG_SHADOW_OFFSET_YPOS, 1); // NOTE(zaklaus): draw shadow
debug_draw_list(items, xpos, ypos, 0);
}
DrawNuklear(nk_ctx);
}
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) {

View File

@ -1,4 +1,4 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "world/blocks.h"
#include "models/items.h"
#include "net/network.h"
@ -49,9 +49,7 @@ ActSpawnSelItem(void) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
entity_set_position(e, origin->x, origin->y);
}
void

View File

@ -0,0 +1,67 @@
// debug tools written with Nuklear UI
#include "models/assets.h"
#include "world/blocks.h"
#include "models/items.h"
void ToolAssetInspector(void) {
if (nk_begin(nk_ctx, "Asset Inspector", nk_rect(400, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
{
for (int i = 0; i < MAX_ASSETS; i++) {
uint16_t idx = assets_find(i);
if (idx != ASSET_INVALID && nk_tree_push_id(nk_ctx, NK_TREE_TAB, asset_names[i], NK_MINIMIZED, i)) {
{
// draw kind
const char *asset_kind_name = assets_get_kind_name(idx);
nk_labelf(nk_ctx, NK_TEXT_LEFT, "kind: %s", asset_kind_name);
nk_labelf(nk_ctx, NK_TEXT_LEFT, "spawnable entity: %s", entity_spawn_provided(i) ? "true" : "false");
// draw block
block_id blk_id = blocks_find(i);
if (blk_id != 0xF) {
if (nk_tree_push_id(nk_ctx, NK_TREE_NODE, "block", NK_MINIMIZED, i)) {
{
nk_labelf(nk_ctx, NK_TEXT_LEFT, "symbol: %s", zpl_bprintf("%c", blocks_get_symbol(blk_id)));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "flags: %u", blocks_get_flags(blk_id));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "drag: %f", blocks_get_drag(blk_id));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "friction: %f", blocks_get_friction(blk_id));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "bounce: %f", blocks_get_bounce(blk_id));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "velx: %f", blocks_get_velx(blk_id));
nk_labelf(nk_ctx, NK_TEXT_LEFT, "vely: %f", blocks_get_vely(blk_id));
}
nk_tree_pop(nk_ctx);
}
}
// draw item
item_id it_id = item_find_no_proxy(i);
if (it_id != ASSET_INVALID) {
if (nk_tree_push_id(nk_ctx, NK_TREE_NODE, "item", NK_MINIMIZED, i)) {
{
item_desc it = item_get_desc(it_id);
if (nk_button_label(nk_ctx, "spawn")) {
ecs_entity_t e = item_spawn(i, 1);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y);
}
nk_labelf(nk_ctx, NK_TEXT_LEFT, "usage: %d", it.usage);
nk_labelf(nk_ctx, NK_TEXT_LEFT, "attachment: %d", it.attachment);
nk_labelf(nk_ctx, NK_TEXT_LEFT, "max quantity: %d", it.max_quantity);
nk_labelf(nk_ctx, NK_TEXT_LEFT, "has storage: %s", it.has_storage ? "true" : "false");
// todo: draw item-specific data
}
nk_tree_pop(nk_ctx);
}
}
}
nk_tree_pop(nk_ctx);
}
}
nk_end(nk_ctx);
}
}

View File

@ -1,4 +1,4 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "raylib.h"
#include "platform/platform.h"
#include "net/network.h"

View File

@ -94,7 +94,7 @@ uint16_t assets_find(asset_id id) {
return i;
}
ZPL_PANIC("Unknown asset id: %d\n", id);
//ZPL_PANIC("Unknown asset id: %d\n", id);
return ASSET_INVALID;
}
@ -102,6 +102,11 @@ asset_kind assets_get_kind(uint16_t id) {
return assets[id].kind;
}
const char* assets_get_kind_name(uint16_t id) {
static const char* names[] = { "Texture", "Animated Texture", "Sound" };
return names[assets[id].kind];
}
void *assets_get_snd(uint16_t id) {
return (void*)&assets[id].snd;;
}

View File

@ -18,6 +18,7 @@ void assets_destroy(void);
uint16_t assets_find(asset_id id);
asset_kind assets_get_kind(uint16_t id);
const char *assets_get_kind_name(uint16_t id);
void *assets_get_snd(uint16_t id);
void *assets_get_tex(uint16_t id);
uint16_t assets_resolve_proxy(uint16_t id);

View File

@ -47,6 +47,16 @@ uint64_t entity_spawn_id_with_data(uint16_t id, void *udata){
}
return 0;
}
bool entity_spawn_provided(uint16_t id) {
for (size_t i = 0; i < MAX_ENTITY_SPAWNDEFS; ++i){
if (entity_spawnlist[i].id == id){
return true;
}
}
return false;
}
void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
for (size_t i = 0; i < num_ids; i++ ) {
librg_entity_untrack(world_tracker(), ids[i]);

View File

@ -6,6 +6,7 @@
uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */);
uint64_t entity_spawn_id(uint16_t id);
uint64_t entity_spawn_id_with_data(uint16_t id, void* udata);
bool entity_spawn_provided(uint16_t id);
void entity_batch_despawn(uint64_t *ids, size_t num_ids);
void entity_despawn(uint64_t ent_id);
void entity_set_position(uint64_t ent_id, float x, float y);

View File

@ -177,3 +177,8 @@ bool item_get_place_directional(item_id id) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
return items[id].place.directional;
}
item_desc item_get_desc(item_id id) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
return items[id];
}

View File

@ -81,3 +81,4 @@ const Item *item_get_data_const(uint64_t ent);
uint32_t item_max_quantity(item_id id);
item_usage item_get_usage(item_id id);
bool item_get_place_directional(item_id id);
item_desc item_get_desc(item_id id);

View File

@ -6,7 +6,7 @@
#include "world/world.h"
#include "models/entity.h"
#include "debug/debug_replay.h"
#include "dev/debug_replay.h"
pkt_desc pkt_send_keystate_desc[] = {
{ PKT_REAL(pkt_send_keystate, x) },

View File

@ -1,4 +1,4 @@
#include "debug/debug_draw.h"
#include "dev/debug_draw.h"
#include "models/entity.h"
void LeaveVehicle(ecs_iter_t *it) {

View File

@ -4,7 +4,7 @@
#include "world/world.h"
#include "world/blocks.h"
#include "platform/profiler.h"
#include "debug/debug_draw.h"
#include "dev/debug_draw.h"
#include "core/game.h"
#include "core/rules.h"

View File

@ -4,7 +4,7 @@
#include "systems/systems.h"
#include "world/world.h"
#include "world/entity_view.h"
#include "debug/debug_replay.h"
#include "dev/debug_replay.h"
#include "models/items.h"
#include "world/worldgen.h"
#include "platform/platform.h"

View File

@ -10,7 +10,7 @@
#include "world/blocks.h"
#include "models/assets.h"
#include "platform/profiler.h"
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "utils/raylib_helpers.h"
#include "platform/renderer.h"

View File

@ -11,8 +11,8 @@
#include "world/blocks.h"
#include "models/assets.h"
#include "platform/profiler.h"
#include "debug/debug_ui.h"
#include "debug/debug_draw.h"
#include "dev/debug_ui.h"
#include "dev/debug_draw.h"
#include "utils/raylib_helpers.h"
#include "platform/renderer.h"

View File

@ -1,5 +1,6 @@
add_subdirectory(flecs)
add_subdirectory(cwpack)
add_subdirectory(raylib-nuklear)
add_library(vendors-bundle STATIC
sfd.c

View File

@ -0,0 +1,9 @@
root = true
[*]
indent_style = space
charset = utf-8
end_of_line = lf
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -0,0 +1,2 @@
build
.vscode

View File

@ -0,0 +1,4 @@
[submodule "vendor/nuklear"]
path = vendor/nuklear
url = https://github.com/Immediate-Mode-UI/Nuklear.git
ignore = dirty

View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.11)
project(raylib_nuklear
DESCRIPTION "raylib_nuklear: Nuklear immediate mode GUI for raylib."
HOMEPAGE_URL "https://github.com/robloach/raylib-nuklear"
VERSION 4.2.2
LANGUAGES C
)
# raylib-nuklear
add_subdirectory(include)
# Options
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
set(RAYLIB_NUKLEAR_IS_MAIN TRUE)
else()
set(RAYLIB_NUKLEAR_IS_MAIN FALSE)
endif()
option(RAYLIB_NUKLEAR_BUILD_EXAMPLES "Examples" ${RAYLIB_NUKLEAR_IS_MAIN})
# Examples
if (RAYLIB_NUKLEAR_BUILD_EXAMPLES)
add_subdirectory(examples)
# Testing
include(CTest)
enable_testing()
if (BUILD_TESTING)
# set(CTEST_CUSTOM_TESTS_IGNORE
# pkg-config--static
# )
add_subdirectory(test)
endif()
endif()

View File

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

View File

@ -0,0 +1,165 @@
# raylib-nuklear
Use the [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) immediate mode cross-platform GUI library in [raylib](https://www.raylib.com/).
[![raylib-nuklear-example Screenshot](examples/raylib-nuklear-example.png)](examples)
## Usage
1. Since this is a header-only library, you must first define `RAYLIB_NUKLEAR_IMPLEMENTATION` in one of your `.c` files...
``` c
#define RAYLIB_NUKLEAR_IMPLEMENTATION
```
2. Include the [`raylib-nuklear.h`](include/raylib-nuklear.h) file...
``` c
#include "path/to/raylib-nuklear.h"
```
3. Use `InitNuklear(fontSize)` or `InitNuklearEx(font, fontSize)` to create the nuklear context...
``` c
struct nk_context *ctx = InitNuklear(10);
```
4. Build your Nuklear GUI through the standard [Nuklear API](https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window)
5. Update the input for the GUI using `UpdateNuklear(ctx)`
6. Render the context using `DrawNuklear(ctx)`
7. Destroy the nuklear context with `UnloadNuklear(ctx)`
## Example
``` c
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
int main() {
InitWindow(640, 480, "raylib-nuklear example");
// Create the Nuklear Context
int fontSize = 10;
struct nk_context *ctx = InitNuklear(fontSize);
while (!WindowShouldClose()) {
// Update the Nuklear context, along with input
UpdateNuklear(ctx);
// Nuklear GUI Code
// https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window
if (nk_begin(ctx, "Nuklear", nk_rect(100, 100, 220, 220),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
if (nk_button_label(ctx, "Button")) {
// Button was clicked!
}
}
nk_end(ctx);
// Render
BeginDrawing();
ClearBackground(RAYWHITE);
// Render the Nuklear GUI
DrawNuklear(ctx);
EndDrawing();
}
// De-initialize the Nuklear GUI
UnloadNuklear(ctx);
CloseWindow();
return 0;
}
```
## API
``` c
struct nk_context* InitNuklear(int fontSize); // Initialize the Nuklear GUI context
struct nk_context* InitNuklearEx(Font font, float fontSize); // Initialize the Nuklear GUI context, with a custom font
void UpdateNuklear(struct nk_context * ctx); // Update the input state and internal components for Nuklear
void DrawNuklear(struct nk_context * ctx); // Render the Nuklear GUI on the screen
void UnloadNuklear(struct nk_context * ctx); // Deinitialize the Nuklear context
struct nk_color ColorToNuklear(Color color); // Convert a raylib Color to a Nuklear color object
struct nk_colorf ColorToNuklearF(Color color); // Convert a raylib Color to a Nuklear floating color
struct Color ColorFromNuklear(struct nk_color color); // Convert a Nuklear color to a raylib Color
struct Color ColorFromNuklearF(struct nk_colorf color); // Convert a Nuklear floating color to a raylib Color
struct Rectangle RectangleFromNuklear(struct nk_context * ctx, struct nk_rect rect); // Convert a Nuklear rectangle to a raylib Rectangle
struct nk_rect RectangleToNuklear(struct nk_context * ctx, Rectangle rect); // Convert a raylib Rectangle to a Nuklear Rectangle
struct nk_image TextureToNuklear(Texture tex); // Convert a raylib Texture to A Nuklear image
struct Texture TextureFromNuklear(struct nk_image img); // Convert a Nuklear image to a raylib Texture
struct nk_image LoadNuklearImage(const char* path); // Load a Nuklear image
void UnloadNuklearImage(struct nk_image img); // Unload a Nuklear image. And free its data
void CleanupNuklearImage(struct nk_image img); // Frees the data stored by the Nuklear image
void SetNuklearScaling(struct nk_context * ctx, float scaling); // Scale the graphical user interface larger or smaller (1 is the default)
float GetNuklearScaling(struct nk_context * ctx); // Retrieves the scale of the given Nuklear contextgit
```
See the [Nuklear API documenation](https://immediate-mode-ui.github.io/Nuklear/doc/nuklear.html) for more how to use Nuklear.
## Comparision
There are a few other graphical user interface solutions out there for use with raylib. While every project's needs differ, this aims to compare and contrast each one. In general, however, if you're unsure which GUI to use, use raygui.
### Nuklear
[Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) is a fully fledged immediate mode GUI library, providing a full set of controls and widgets.
#### Pros
- Portability, as it's written in C99
- Automatic layouts
- Lots of controls
- [Documentation](https://immediate-mode-ui.github.io/Nuklear/doc/index.html)
- Stable API
#### Cons
- Larger code size, which can result in slower compile time
- Slightly more complex API than raygui
### raygui
[raygui](https://github.com/raysan5/raygui) is a companion library for raylib, and is a tiny, lightweight immediate mode GUI.
#### Pros
- Targets the same platforms as raylib
- Tiny code size
- Minimal API
- Easy to use
- Matches the coding conventions of raylib
#### Cons
- No automatic layouts
- No documentation
- Not many advanced controls
### ImGui
[ImGui](https://github.com/ocornut/imgui), used in raylib with [rlImGui](https://github.com/raylib-extras/rlImGui), is a very powerful graphical user interface for C++.
#### Pros
- Pretty much an industry standard
- Lots of advanced controls
- Automatic layouts
#### Cons
- Requires C++
## Development
While this project uses CMake, CMake is not required in order to use *raylib-nuklear*.
```
git submodule update --init
mkdir build
cd build
cmake ..
make
./example/raylib-nuklear-example
make test
```
## License
*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.

View File

@ -0,0 +1,77 @@
# raylib
find_package(raylib QUIET)
if (NOT raylib_FOUND)
include(FetchContent)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG 4.2.0
)
FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED) # Have we downloaded raylib yet?
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(raylib)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_GAMES OFF CACHE BOOL "" FORCE)
add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
endif()
endif()
# raylib-nuklear-example
add_executable(raylib-nuklear-example
raylib-nuklear-example.c
)
target_link_libraries(raylib-nuklear-example PUBLIC
raylib
raylib_nuklear
)
# raylib-nuklear-demo
add_executable(raylib-nuklear-demo
raylib-nuklear-demo.c
)
target_link_libraries(raylib-nuklear-demo PUBLIC
raylib
raylib_nuklear
)
# raylib-nuklear-font
add_executable(raylib-nuklear-font
raylib-nuklear-font.c
)
target_link_libraries(raylib-nuklear-font PUBLIC
raylib
raylib_nuklear
)
# raylib-nuklear-texture
add_executable(raylib-nuklear-texture
raylib-nuklear-texture.c
)
target_link_libraries(raylib-nuklear-texture PUBLIC
raylib
raylib_nuklear
)
# Target C99
set_property(TARGET raylib-nuklear-example PROPERTY C_STANDARD 99)
set_property(TARGET raylib-nuklear-demo PROPERTY C_STANDARD 99)
set_property(TARGET raylib-nuklear-font PROPERTY C_STANDARD 99)
set_property(TARGET raylib-nuklear-texture PROPERTY C_STANDARD 99)
# Enable warnings
if(MSVC)
target_compile_options(raylib-nuklear-example PRIVATE /W4 /WX)
target_compile_options(raylib-nuklear-demo PRIVATE /W4 /WX)
target_compile_options(raylib-nuklear-font PRIVATE /W4 /WX)
target_compile_options(raylib-nuklear-texture PRIVATE /W4 /WX)
else()
target_compile_options(raylib-nuklear-example PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_compile_options(raylib-nuklear-demo PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_compile_options(raylib-nuklear-font PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_compile_options(raylib-nuklear-texture PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
# Resources
configure_file(resources/anonymous_pro_bold.ttf resources/anonymous_pro_bold.ttf COPYONLY)
configure_file(resources/test-image.png resources/test-image.png COPYONLY)

View File

@ -0,0 +1,4 @@
Fonts used in examples are provided under a free and permissive license.
Check individual licenses for details:
- [Anonymous Pro] by Mark Simonson - https://fonts.google.com/specimen/Anonymous+Pro

View File

@ -0,0 +1,158 @@
/* nuklear - 1.32.0 - public domain */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include "raylib.h"
//#define NK_INCLUDE_FIXED_TYPES
//#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
//#define NK_INCLUDE_DEFAULT_ALLOCATOR
//#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
//#define NK_INCLUDE_FONT_BAKING
//#define NK_INCLUDE_DEFAULT_FONT
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800
/* ===============================================================
*
* EXAMPLE
*
* ===============================================================*/
/* This are some code examples to provide a small overview of what can be
* done with this library. To try out an example uncomment the defines */
#define INCLUDE_ALL
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
//#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../vendor/nuklear/demo/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../vendor/nuklear/demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../vendor/nuklear/demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../vendor/nuklear/demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../vendor/nuklear/demo/common/node_editor.c"
#endif
/* ===============================================================
*
* DEMO
*
* ===============================================================*/
int main(void)
{
struct nk_context *ctx;
struct nk_colorf bg;
/* Platform */
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "[raylib-nuklear] demo");
SetTargetFPS(60);
/* GUI */
ctx = InitNuklear(10);
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
while (!WindowShouldClose())
{
/* Input */
UpdateNuklear(ctx);
/* GUI */
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
nk_layout_row_static(ctx, 30, 80, 1);
if (nk_button_label(ctx, "button"))
TraceLog(LOG_INFO, "button pressed!");
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 22, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "background:", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 1);
if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
bg = nk_color_picker(ctx, bg, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(ctx);
}
}
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(ctx);
#endif
/* ----------------------------------------- */
/* Draw */
BeginDrawing();
{
ClearBackground(ColorFromNuklearF(bg));
DrawNuklear(ctx);
}
EndDrawing();
}
UnloadNuklear(ctx); // Unload the Nuklear GUI
CloseWindow();
return 0;
}

View File

@ -0,0 +1,110 @@
/**********************************************************************************************
*
* raylib-nuklear-example - Example of using Nuklear with Raylib.
*
* LICENSE: zlib/libpng
*
* nuklear_raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software:
*
* Copyright (c) 2020 Rob Loach (@RobLoach)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 700;
const int screenHeight = 394;
InitWindow(screenWidth, screenHeight, "[raylib-nuklear] example");
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
/* GUI */
struct nk_colorf bg = ColorToNuklearF(SKYBLUE);
struct nk_context *ctx = InitNuklear(10);
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
UpdateNuklear(ctx);
// GUI
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
nk_layout_row_static(ctx, 30, 80, 1);
if (nk_button_label(ctx, "button"))
TraceLog(LOG_INFO, "button pressed");
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 25, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "background:", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 1);
if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
bg = nk_color_picker(ctx, bg, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(ctx);
}
}
nk_end(ctx);
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(ColorFromNuklearF(bg));
DrawNuklear(ctx);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadNuklear(ctx); // Unload the Nuklear GUI
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,114 @@
/**********************************************************************************************
*
* raylib-nuklear-font - Example of using Nuklear with a custom Raylib font.
*
* LICENSE: zlib/libpng
*
* 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:
*
* Copyright (c) 2020 Rob Loach (@RobLoach)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
const int fontSize = 14;
InitWindow(screenWidth, screenHeight, "[raylib-nuklear] font example");
Font font = LoadFontEx("resources/anonymous_pro_bold.ttf", fontSize, NULL, 0);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
/* GUI */
struct nk_colorf bg = ColorToNuklearF(SKYBLUE);
struct nk_context *ctx = InitNuklearEx(font, fontSize);
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
UpdateNuklear(ctx);
// GUI
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
nk_layout_row_static(ctx, 30, 80, 1);
if (nk_button_label(ctx, "button"))
TraceLog(LOG_INFO, "button pressed");
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 25, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "background:", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 1);
if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
bg = nk_color_picker(ctx, bg, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(ctx);
}
}
nk_end(ctx);
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(ColorFromNuklearF(bg));
DrawNuklear(ctx);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadNuklear(ctx); // Unload the Nuklear GUI
UnloadFont(font);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -0,0 +1,59 @@
/* ===============================================================
*
* EXAMPLE
*
* ===============================================================*/
/*
This example shows how to use the image API from raylib nuklear.
And then display it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <raylib.h>
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
int main()
{
InitWindow(1280, 720, "[raylib-nuklear] - Texture/Image");
// Initialize the context
struct nk_context* ctx = InitNuklear(20);
// Scale up the Nuklear GUI
SetNuklearScaling(ctx, 1.2f);
// Load the nk_image
struct nk_image img = LoadNuklearImage("resources/test-image.png");
while (!WindowShouldClose())
{
// Input
UpdateNuklear(ctx);
// The window called "Image example" is opend
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))
{
// Setup the layout
nk_layout_row_static(ctx, img.h, img.w, 1);
// Draw the image
nk_image(ctx, img);
}
nk_end(ctx);
// Draw the GUI
BeginDrawing();
ClearBackground(RAYWHITE);
DrawNuklear(ctx);
EndDrawing();
}
// Unload the Nuklear image
UnloadNuklearImage(img);
CloseWindow();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -0,0 +1,8 @@
# raylib_nuklear
add_library(raylib_nuklear INTERFACE)
target_include_directories(raylib_nuklear INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
install(FILES
raylib-nuklear.h
nuklear.h
DESTINATION include
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,911 @@
/**********************************************************************************************
*
* raylib-nuklear - Nuklear for Raylib.
*
* FEATURES:
* - Use the nuklear immediate-mode graphical user interface in raylib.
*
* DEPENDENCIES:
* - raylib 4.2 https://www.raylib.com/
* - nuklear https://github.com/Immediate-Mode-UI/Nuklear
*
* LICENSE: zlib/libpng
*
* 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:
*
* Copyright (c) 2020 Rob Loach (@RobLoach)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RAYLIB_NUKLEAR_H
#define RAYLIB_NUKLEAR_H
#include "raylib.h"
// Nuklear defines
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_COMMAND_USERDATA
// TODO: Replace NK_INCLUDE_DEFAULT_ALLOCATOR with MemAlloc() and MemFree()
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_COMMAND_USERDATA
// TODO: Figure out if we can use STANDARD_BOOL here?
//#define NK_INCLUDE_STANDARD_BOOL
//#ifndef NK_BOOL
//#define NK_BOOL bool
//#endif // NK_BOOL
#ifndef NK_ASSERT
#define NK_ASSERT(condition) do { if (!(condition)) { TraceLog(LOG_WARNING, "NUKLEAR: Failed assert \"%s\" (%s:%i)", #condition, "nuklear.h", __LINE__); }} while (0)
#endif // NK_ASSERT
#include "nuklear.h"
#ifdef __cplusplus
extern "C" {
#endif
NK_API struct nk_context* InitNuklear(int fontSize); // Initialize the Nuklear GUI context
NK_API struct nk_context* InitNuklearEx(Font font, float fontSize); // Initialize the Nuklear GUI context, with a custom font
NK_API void UpdateNuklear(struct nk_context * ctx); // Update the input state and internal components for Nuklear
NK_API void DrawNuklear(struct nk_context * ctx); // Render the Nuklear GUI on the screen
NK_API void UnloadNuklear(struct nk_context * ctx); // Deinitialize the Nuklear context
NK_API struct nk_color ColorToNuklear(Color color); // Convert a raylib Color to a Nuklear color object
NK_API struct nk_colorf ColorToNuklearF(Color color); // Convert a raylib Color to a Nuklear floating color
NK_API struct Color ColorFromNuklear(struct nk_color color); // Convert a Nuklear color to a raylib Color
NK_API struct Color ColorFromNuklearF(struct nk_colorf color); // Convert a Nuklear floating color to a raylib Color
NK_API struct Rectangle RectangleFromNuklear(struct nk_context * ctx, struct nk_rect rect); // Convert a Nuklear rectangle to a raylib Rectangle
NK_API struct nk_rect RectangleToNuklear(struct nk_context * ctx, Rectangle rect); // Convert a raylib Rectangle to a Nuklear Rectangle
NK_API struct nk_image TextureToNuklear(Texture tex); // Convert a raylib Texture to A Nuklear image
NK_API struct Texture TextureFromNuklear(struct nk_image img); // Convert a Nuklear image to a raylib Texture
NK_API struct nk_image LoadNuklearImage(const char* path); // Load a Nuklear image
NK_API void UnloadNuklearImage(struct nk_image img); // Unload a Nuklear image. And free its data
NK_API void CleanupNuklearImage(struct nk_image img); // Frees the data stored by the Nuklear image
NK_API void SetNuklearScaling(struct nk_context * ctx, float scaling); // Sets the scaling for the given Nuklear context
NK_API float GetNuklearScaling(struct nk_context * ctx); // Retrieves the scaling of the given Nuklear context
#ifdef __cplusplus
}
#endif
#endif // RAYLIB_NUKLEAR_H
#ifdef RAYLIB_NUKLEAR_IMPLEMENTATION
#ifndef RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
#define RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
// Math
#ifndef NK_COS
#define NK_COS cosf
#endif // NK_COS
#ifndef NK_SIN
#define NK_SIN sinf
#endif // NK_SIN
#ifndef NK_INV_SQRT
#define NK_INV_SQRT(value) (1.0f / sqrtf(value))
#endif // NK_INV_SQRT
#define NK_IMPLEMENTATION
#define NK_KEYSTATE_BASED_INPUT
#include "nuklear.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef RAYLIB_NUKLEAR_DEFAULT_FONTSIZE
/**
* The default font size that is used when a font size is not provided.
*/
#define RAYLIB_NUKLEAR_DEFAULT_FONTSIZE 10
#endif // RAYLIB_NUKLEAR_DEFAULT_FONTSIZE
#ifndef RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS
/**
* The amount of segments used when drawing an arc.
*
* @see NK_COMMAND_ARC_FILLED
*/
#define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 20
#endif // RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS
#ifndef RAYLIB_NUKLEAR_ROUNDING_SCALE
/**
* The default scaling to apply for rounded borders.
*/
#define RAYLIB_NUKLEAR_ROUNDING_SCALE 4.0f
#endif
/**
* The user data that's leverages internally through Nuklear.
*/
typedef struct NuklearUserData {
float scaling;
} NuklearUserData;
/**
* Nuklear callback; Get the width of the given text.
*
* @internal
*/
NK_API float
nk_raylib_font_get_text_width(nk_handle handle, float height, const char *text, int len)
{
NK_UNUSED(handle);
if (len > 0) {
// Grab the text with the cropped length so that it only measures the desired string length.
const char* subtext = TextSubtext(text, 0, len);
return (float)MeasureText(subtext, (int)height);
}
return 0;
}
/**
* Nuklear callback; Get the width of the given text (userFont version)
*
* @internal
*/
NK_API float
nk_raylib_font_get_text_width_user_font(nk_handle handle, float height, const char *text, int len)
{
if (len > 0) {
// Grab the text with the cropped length so that it only measures the desired string length.
const char* subtext = TextSubtext(text, 0, len);
// Spacing is determined by the font size divided by 10.
return MeasureTextEx(*(Font*)handle.ptr, subtext, height, height / 10.0f).x;
}
return 0;
}
/**
* Nuklear callback; Paste the current clipboard.
*
* @internal
*/
NK_API void
nk_raylib_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = GetClipboardText();
NK_UNUSED(usr);
if (text != NULL) {
nk_textedit_paste(edit, text, (int)TextLength(text));
}
}
/**
* Nuklear callback; Copy the given text.
*
* @internal
*/
NK_API void
nk_raylib_clipboard_copy(nk_handle usr, const char *text, int len)
{
NK_UNUSED(usr);
NK_UNUSED(len);
SetClipboardText(text);
}
/**
* Initialize the Nuklear context for use with Raylib, with the given Nuklear user font.
*
* @param userFont The Nuklear user font to initialize the Nuklear context with.
*
* @internal
*/
NK_API struct nk_context*
InitNuklearContext(struct nk_user_font* userFont)
{
struct nk_context* ctx = (struct nk_context*)MemAlloc(sizeof(struct nk_context));
struct NuklearUserData* userData = (struct NuklearUserData*)MemAlloc(sizeof(struct NuklearUserData));
// Clipboard
ctx->clip.copy = nk_raylib_clipboard_copy;
ctx->clip.paste = nk_raylib_clipboard_paste;
ctx->clip.userdata = nk_handle_ptr(0);
// Create the nuklear environment.
if (nk_init_default(ctx, userFont) == 0) {
TraceLog(LOG_ERROR, "NUKLEAR: Failed to initialize nuklear");
return NULL;
}
// Set the internal user data.
userData->scaling = 1.0f;
nk_handle userDataHandle;
userDataHandle.id = 1;
userDataHandle.ptr = (void*)userData;
nk_set_user_data(ctx, userDataHandle);
TraceLog(LOG_INFO, "NUKLEAR: Initialized GUI");
return ctx;
}
/**
* Initialize the Nuklear context for use with Raylib.
*
* @param fontSize The size of the font to use for GUI text. Use 0 to use the default font size of 10.
*
* @return The nuklear context, or NULL on error.
*/
NK_API struct nk_context*
InitNuklear(int fontSize)
{
// User font.
struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font));
// Use the default font size if desired.
if (fontSize <= 0) {
fontSize = RAYLIB_NUKLEAR_DEFAULT_FONTSIZE;
}
userFont->height = (float)fontSize;
userFont->width = nk_raylib_font_get_text_width;
userFont->userdata = nk_handle_ptr(0);
// Nuklear context.
return InitNuklearContext(userFont);
}
/**
* Initialize the Nuklear context for use with Raylib, with a supplied custom font.
*
* @param font The custom raylib font to use with Nuklear.
* @param fontSize The desired size of the font. Use 0 to set the default size of 10.
*
* @return The nuklear context, or NULL on error.
*/
NK_API struct nk_context*
InitNuklearEx(Font font, float fontSize)
{
// Copy the font to a new raylib font pointer.
struct Font* newFont = (struct Font*)MemAlloc(sizeof(struct Font));
// Use the default font size if desired.
if (fontSize <= 0.0f) {
fontSize = (float)RAYLIB_NUKLEAR_DEFAULT_FONTSIZE;
}
newFont->baseSize = font.baseSize;
newFont->glyphCount = font.glyphCount;
newFont->glyphPadding = font.glyphPadding;
newFont->glyphs = font.glyphs;
newFont->recs = font.recs;
newFont->texture = font.texture;
// Create the nuklear user font.
struct nk_user_font* userFont = (struct nk_user_font*)MemAlloc(sizeof(struct nk_user_font));
userFont->userdata = nk_handle_ptr(newFont);
userFont->height = fontSize;
userFont->width = nk_raylib_font_get_text_width_user_font;
// Nuklear context.
return InitNuklearContext(userFont);
}
/**
* Convert the given Nuklear color to a raylib color.
*/
NK_API Color
ColorFromNuklear(struct nk_color color)
{
Color rc;
rc.a = color.a;
rc.r = color.r;
rc.g = color.g;
rc.b = color.b;
return rc;
}
/**
* Convert the given raylib color to a Nuklear color.
*/
NK_API struct nk_color
ColorToNuklear(Color color)
{
struct nk_color rc;
rc.a = color.a;
rc.r = color.r;
rc.g = color.g;
rc.b = color.b;
return rc;
}
/**
* Convert the given Nuklear float color to a raylib color.
*/
NK_API Color
ColorFromNuklearF(struct nk_colorf color)
{
return ColorFromNuklear(nk_rgba_cf(color));
}
/**
* Convert the given raylib color to a raylib float color.
*/
NK_API struct nk_colorf
ColorToNuklearF(Color color)
{
return nk_color_cf(ColorToNuklear(color));
}
/**
* Draw the given Nuklear context in raylib.
*
* @param ctx The nuklear context.
*/
NK_API void
DrawNuklear(struct nk_context * ctx)
{
const struct nk_command *cmd;
const float scale = GetNuklearScaling(ctx);
nk_foreach(cmd, ctx) {
switch (cmd->type) {
case NK_COMMAND_NOP: {
break;
}
case NK_COMMAND_SCISSOR: {
// TODO(RobLoach): Verify if NK_COMMAND_SCISSOR works.
const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
BeginScissorMode((int)(s->x * scale), (int)(s->y * scale), (int)(s->w * scale), (int)(s->h * scale));
} break;
case NK_COMMAND_LINE: {
const struct nk_command_line *l = (const struct nk_command_line *)cmd;
Color color = ColorFromNuklear(l->color);
Vector2 startPos = {(float)l->begin.x * scale, (float)l->begin.y * scale};
Vector2 endPos = {(float)l->end.x * scale, (float)l->end.y * scale};
DrawLineEx(startPos, endPos, l->line_thickness * scale, color);
} break;
case NK_COMMAND_CURVE: {
const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
Color color = ColorFromNuklear(q->color);
// Vector2 start = {(float)q->begin.x, (float)q->begin.y};
Vector2 start = {(float)q->begin.x * scale, (float)q->begin.y * scale};
// Vector2 controlPoint1 = (Vector2){q->ctrl[0].x, q->ctrl[0].y};
// Vector2 controlPoint2 = (Vector2){q->ctrl[1].x, q->ctrl[1].y};
// Vector2 end = {(float)q->end.x, (float)q->end.y};
Vector2 end = {(float)q->end.x * scale, (float)q->end.y * scale};
// TODO: Encorporate segmented control point bezier curve?
// DrawLineBezier(start, controlPoint1, (float)q->line_thickness, color);
// DrawLineBezier(controlPoint1, controlPoint2, (float)q->line_thickness, color);
// DrawLineBezier(controlPoint2, end, (float)q->line_thickness, color);
// DrawLineBezier(start, end, (float)q->line_thickness, color);
DrawLineBezier(start, end, (float)q->line_thickness * scale, color);
} break;
case NK_COMMAND_RECT: {
const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
Color color = ColorFromNuklear(r->color);
Rectangle rect = {(float)r->x * scale, (float)r->y * scale, (float)r->w * scale, (float)r->h * scale};
float roundness = (float)r->rounding * RAYLIB_NUKLEAR_ROUNDING_SCALE / (rect.width + rect.height);
if (roundness > 0.0f) {
DrawRectangleRoundedLines(rect, roundness, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, (float)r->line_thickness * scale, color);
}
else {
DrawRectangleLinesEx(rect, r->line_thickness * scale, color);
}
} break;
case NK_COMMAND_RECT_FILLED: {
const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
Color color = ColorFromNuklear(r->color);
Rectangle rect = {(float)r->x * scale, (float)r->y * scale, (float)r->w * scale, (float)r->h * scale};
float roundness = (float)r->rounding * RAYLIB_NUKLEAR_ROUNDING_SCALE / (rect.width + rect.height);
if (roundness > 0.0f) {
DrawRectangleRounded(rect, roundness, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color);
}
else {
DrawRectangleRec(rect, color);
}
} break;
case NK_COMMAND_RECT_MULTI_COLOR: {
const struct nk_command_rect_multi_color* rectangle = (const struct nk_command_rect_multi_color *)cmd;
Rectangle position = {(float)rectangle->x * scale, (float)rectangle->y * scale, (float)rectangle->w * scale, (float)rectangle->h * scale};
Color left = ColorFromNuklear(rectangle->left);
Color top = ColorFromNuklear(rectangle->top);
Color bottom = ColorFromNuklear(rectangle->bottom);
Color right = ColorFromNuklear(rectangle->right);
DrawRectangleGradientEx(position, left, bottom, right, top);
} break;
case NK_COMMAND_CIRCLE: {
const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
Color color = ColorFromNuklear(c->color);
DrawEllipseLines((int)(c->x * scale + c->w * scale / 2.0f), (int)(c->y * scale + c->h * scale / 2.0f), (int)(c->w * scale / 2.0f), (int)(c->h * scale / 2.0f), color);
} break;
case NK_COMMAND_CIRCLE_FILLED: {
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
Color color = ColorFromNuklear(c->color);
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);
} break;
case NK_COMMAND_ARC: {
const struct nk_command_arc *a = (const struct nk_command_arc*)cmd;
Color color = ColorFromNuklear(a->color);
Vector2 center = {(float)a->cx, (float)a->cy};
DrawRingLines(center, 0, a->r * scale, a->a[0] * RAD2DEG - 45, a->a[1] * RAD2DEG - 45, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color);
} break;
case NK_COMMAND_ARC_FILLED: {
const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled*)cmd;
Color color = ColorFromNuklear(a->color);
Vector2 center = {(float)a->cx * scale, (float)a->cy * scale};
DrawRing(center, 0, a->r * scale, a->a[0] * RAD2DEG - 45, a->a[1] * RAD2DEG - 45, RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS, color);
} break;
case NK_COMMAND_TRIANGLE: {
const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
Color color = ColorFromNuklear(t->color);
Vector2 point1 = {(float)t->b.x * scale, (float)t->b.y * scale};
Vector2 point2 = {(float)t->a.x * scale, (float)t->a.y * scale};
Vector2 point3 = {(float)t->c.x * scale, (float)t->c.y * scale};
DrawTriangleLines(point1, point2, point3, color);
} break;
case NK_COMMAND_TRIANGLE_FILLED: {
const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
Color color = ColorFromNuklear(t->color);
Vector2 point1 = {(float)t->b.x * scale, (float)t->b.y * scale};
Vector2 point2 = {(float)t->a.x * scale, (float)t->a.y * scale};
Vector2 point3 = {(float)t->c.x * scale, (float)t->c.y * scale};
DrawTriangle(point1, point2, point3, color);
} break;
case NK_COMMAND_POLYGON: {
// TODO: Confirm Polygon
const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
Color color = ColorFromNuklear(p->color);
struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
unsigned short i;
for (i = 0; i < p->point_count; i++) {
points[i].x = p->points[i].x * scale;
points[i].y = p->points[i].y * scale;
}
DrawTriangleStrip(points, p->point_count, color);
MemFree(points);
} break;
case NK_COMMAND_POLYGON_FILLED: {
// TODO: Polygon filled expects counter clockwise order
const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
Color color = ColorFromNuklear(p->color);
struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
unsigned short i;
for (i = 0; i < p->point_count; i++) {
points[i].x = p->points[i].x * scale;
points[i].y = p->points[i].y * scale;
}
DrawTriangleFan(points, p->point_count, color);
MemFree(points);
} break;
case NK_COMMAND_POLYLINE: {
// TODO: Polygon expects counter clockwise order
const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
Color color = ColorFromNuklear(p->color);
struct Vector2* points = (struct Vector2*)MemAlloc(p->point_count * (unsigned short)sizeof(Vector2));
unsigned short i;
for (i = 0; i < p->point_count; i++) {
points[i].x = p->points[i].x * scale;
points[i].y = p->points[i].y * scale;
}
DrawTriangleStrip(points, p->point_count, color);
MemFree(points);
} break;
case NK_COMMAND_TEXT: {
const struct nk_command_text *text = (const struct nk_command_text*)cmd;
Color color = ColorFromNuklear(text->foreground);
float fontSize = text->font->height * scale;
Font* font = (Font*)text->font->userdata.ptr;
if (font != NULL) {
Vector2 position = {(float)text->x * scale, (float)text->y * scale};
DrawTextEx(*font, (const char*)text->string, position, fontSize, fontSize / 10.0f, color);
}
else {
DrawText((const char*)text->string, (int)(text->x * scale), (int)(text->y * scale), (int)fontSize, color);
}
} break;
case NK_COMMAND_IMAGE: {
const struct nk_command_image *i = (const struct nk_command_image *)cmd;
Texture texture = *(Texture*)i->img.handle.ptr;
Rectangle source = {0, 0, (float)texture.width, (float)texture.height};
Rectangle dest = {(float)i->x * scale, (float)i->y * scale, (float)i->w * scale, (float)i->h * scale};
Vector2 origin = {0, 0};
Color tint = ColorFromNuklear(i->col);
DrawTexturePro(texture, source, dest, origin, 0, tint);
} break;
case NK_COMMAND_CUSTOM: {
TraceLog(LOG_WARNING, "NUKLEAR: Unverified custom callback implementation NK_COMMAND_CUSTOM");
const struct nk_command_custom *custom = (const struct nk_command_custom *)cmd;
custom->callback(NULL, (short)(custom->x * scale), (short)(custom->y * scale), (unsigned short)(custom->w * scale), (unsigned short)(custom->h * scale), custom->callback_data);
} break;
default: {
TraceLog(LOG_WARNING, "NUKLEAR: Missing implementation %i", cmd->type);
} break;
}
}
nk_clear(ctx);
}
/**
* Update the Nuklear context for the keyboard input from raylib.
*
* @param ctx The nuklear context.
*
* @internal
*/
NK_API void nk_raylib_input_keyboard(struct nk_context * ctx)
{
bool control = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);
bool shift = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
nk_input_key(ctx, NK_KEY_SHIFT, shift);
nk_input_key(ctx, NK_KEY_CTRL, control);
nk_input_key(ctx, NK_KEY_DEL, IsKeyDown(KEY_DELETE));
nk_input_key(ctx, NK_KEY_ENTER, IsKeyDown(KEY_ENTER) || IsKeyDown(KEY_KP_ENTER));
nk_input_key(ctx, NK_KEY_TAB, IsKeyDown(KEY_TAB));
nk_input_key(ctx, NK_KEY_BACKSPACE, IsKeyDown(KEY_BACKSPACE));
nk_input_key(ctx, NK_KEY_COPY, IsKeyPressed(KEY_C) && control);
nk_input_key(ctx, NK_KEY_CUT, IsKeyPressed(KEY_X) && control);
nk_input_key(ctx, NK_KEY_PASTE, IsKeyPressed(KEY_V) && control);
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, IsKeyPressed(KEY_B) && control);
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, IsKeyPressed(KEY_E) && control);
nk_input_key(ctx, NK_KEY_TEXT_UNDO, IsKeyDown(KEY_Z) && control);
nk_input_key(ctx, NK_KEY_TEXT_REDO, IsKeyDown(KEY_R) && control);
nk_input_key(ctx, NK_KEY_TEXT_SELECT_ALL, IsKeyDown(KEY_A) && control);
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, IsKeyDown(KEY_LEFT) && control);
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, IsKeyDown(KEY_RIGHT) && control);
nk_input_key(ctx, NK_KEY_LEFT, IsKeyDown(KEY_LEFT) && !control);
nk_input_key(ctx, NK_KEY_RIGHT, IsKeyDown(KEY_RIGHT) && !control);
//nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, IsKeyDown());
//nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, IsKeyDown());
//nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, IsKeyDown());
nk_input_key(ctx, NK_KEY_UP, IsKeyDown(KEY_UP));
nk_input_key(ctx, NK_KEY_DOWN, IsKeyDown(KEY_DOWN));
nk_input_key(ctx, NK_KEY_TEXT_START, IsKeyDown(KEY_HOME));
nk_input_key(ctx, NK_KEY_TEXT_END, IsKeyDown(KEY_END));
nk_input_key(ctx, NK_KEY_SCROLL_START, IsKeyDown(KEY_HOME) && control);
nk_input_key(ctx, NK_KEY_SCROLL_END, IsKeyDown(KEY_END) && control);
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, IsKeyDown(KEY_PAGE_DOWN));
nk_input_key(ctx, NK_KEY_SCROLL_UP, IsKeyDown(KEY_PAGE_UP));
// Keys
if (IsKeyPressed(KEY_APOSTROPHE)) nk_input_unicode(ctx, shift ? 34 : (nk_rune)KEY_APOSTROPHE);
if (IsKeyPressed(KEY_COMMA)) nk_input_unicode(ctx, shift ? 60 : (nk_rune)KEY_COMMA);
if (IsKeyPressed(KEY_MINUS)) nk_input_unicode(ctx, shift ? 95 : (nk_rune)KEY_MINUS);
if (IsKeyPressed(KEY_PERIOD)) nk_input_unicode(ctx, shift ? 62 : (nk_rune)KEY_PERIOD);
if (IsKeyPressed(KEY_SLASH)) nk_input_unicode(ctx, shift ? 63 : (nk_rune)KEY_SLASH);
if (IsKeyPressed(KEY_ZERO)) nk_input_unicode(ctx, shift ? 41 : (nk_rune)KEY_ZERO);
if (IsKeyPressed(KEY_ONE)) nk_input_unicode(ctx, shift ? 33 : (nk_rune)KEY_ONE);
if (IsKeyPressed(KEY_TWO)) nk_input_unicode(ctx, shift ? 64 : (nk_rune)KEY_TWO);
if (IsKeyPressed(KEY_THREE)) nk_input_unicode(ctx, shift ? 35 : (nk_rune)KEY_THREE);
if (IsKeyPressed(KEY_FOUR)) nk_input_unicode(ctx, shift ? 36 : (nk_rune)KEY_FOUR);
if (IsKeyPressed(KEY_FIVE)) nk_input_unicode(ctx, shift ? 37 : (nk_rune)KEY_FIVE);
if (IsKeyPressed(KEY_SIX)) nk_input_unicode(ctx, shift ? 94 : (nk_rune)KEY_SIX);
if (IsKeyPressed(KEY_SEVEN)) nk_input_unicode(ctx, shift ? 38 : (nk_rune)KEY_SEVEN);
if (IsKeyPressed(KEY_EIGHT)) nk_input_unicode(ctx, shift ? 42 : (nk_rune)KEY_EIGHT);
if (IsKeyPressed(KEY_NINE)) nk_input_unicode(ctx, shift ? 40 : (nk_rune)KEY_NINE);
if (IsKeyPressed(KEY_SEMICOLON)) nk_input_unicode(ctx, shift ? 41 : (nk_rune)KEY_SEMICOLON);
if (IsKeyPressed(KEY_EQUAL)) nk_input_unicode(ctx, shift ? 43 : (nk_rune)KEY_EQUAL);
if (IsKeyPressed(KEY_A)) nk_input_unicode(ctx, shift ? KEY_A : KEY_A + 32);
if (IsKeyPressed(KEY_B)) nk_input_unicode(ctx, shift ? KEY_B : KEY_B + 32);
if (IsKeyPressed(KEY_C)) nk_input_unicode(ctx, shift ? KEY_C : KEY_C + 32);
if (IsKeyPressed(KEY_D)) nk_input_unicode(ctx, shift ? KEY_D : KEY_D + 32);
if (IsKeyPressed(KEY_E)) nk_input_unicode(ctx, shift ? KEY_E : KEY_E + 32);
if (IsKeyPressed(KEY_F)) nk_input_unicode(ctx, shift ? KEY_F : KEY_F + 32);
if (IsKeyPressed(KEY_G)) nk_input_unicode(ctx, shift ? KEY_G : KEY_G + 32);
if (IsKeyPressed(KEY_H)) nk_input_unicode(ctx, shift ? KEY_H : KEY_H + 32);
if (IsKeyPressed(KEY_I)) nk_input_unicode(ctx, shift ? KEY_I : KEY_I + 32);
if (IsKeyPressed(KEY_J)) nk_input_unicode(ctx, shift ? KEY_J : KEY_J + 32);
if (IsKeyPressed(KEY_K)) nk_input_unicode(ctx, shift ? KEY_K : KEY_K + 32);
if (IsKeyPressed(KEY_L)) nk_input_unicode(ctx, shift ? KEY_L : KEY_L + 32);
if (IsKeyPressed(KEY_M)) nk_input_unicode(ctx, shift ? KEY_M : KEY_M + 32);
if (IsKeyPressed(KEY_N)) nk_input_unicode(ctx, shift ? KEY_N : KEY_N + 32);
if (IsKeyPressed(KEY_O)) nk_input_unicode(ctx, shift ? KEY_O : KEY_O + 32);
if (IsKeyPressed(KEY_P)) nk_input_unicode(ctx, shift ? KEY_P : KEY_P + 32);
if (IsKeyPressed(KEY_Q)) nk_input_unicode(ctx, shift ? KEY_Q : KEY_Q + 32);
if (IsKeyPressed(KEY_R)) nk_input_unicode(ctx, shift ? KEY_R : KEY_R + 32);
if (IsKeyPressed(KEY_S)) nk_input_unicode(ctx, shift ? KEY_S : KEY_S + 32);
if (IsKeyPressed(KEY_T)) nk_input_unicode(ctx, shift ? KEY_T : KEY_T + 32);
if (IsKeyPressed(KEY_U)) nk_input_unicode(ctx, shift ? KEY_U : KEY_U + 32);
if (IsKeyPressed(KEY_V)) nk_input_unicode(ctx, shift ? KEY_V : KEY_V + 32);
if (IsKeyPressed(KEY_W)) nk_input_unicode(ctx, shift ? KEY_W : KEY_W + 32);
if (IsKeyPressed(KEY_X)) nk_input_unicode(ctx, shift ? KEY_X : KEY_X + 32);
if (IsKeyPressed(KEY_Y)) nk_input_unicode(ctx, shift ? KEY_Y : KEY_Y + 32);
if (IsKeyPressed(KEY_Z)) nk_input_unicode(ctx, shift ? KEY_Z : KEY_Z + 32);
if (IsKeyPressed(KEY_LEFT_BRACKET)) nk_input_unicode(ctx, shift ? 123 : (nk_rune)KEY_LEFT_BRACKET);
if (IsKeyPressed(KEY_BACKSLASH)) nk_input_unicode(ctx, shift ? 124 : (nk_rune)KEY_BACKSLASH);
if (IsKeyPressed(KEY_RIGHT_BRACKET)) nk_input_unicode(ctx, shift ? 125 : (nk_rune)KEY_RIGHT_BRACKET);
if (IsKeyPressed(KEY_GRAVE)) nk_input_unicode(ctx, shift ? 126 : (nk_rune)KEY_GRAVE);
// Functions
if (IsKeyPressed(KEY_SPACE)) nk_input_unicode(ctx, KEY_SPACE);
if (IsKeyPressed(KEY_TAB)) nk_input_unicode(ctx, 9);
// Keypad
if (IsKeyPressed(KEY_KP_0)) nk_input_unicode(ctx, KEY_ZERO);
if (IsKeyPressed(KEY_KP_1)) nk_input_unicode(ctx, KEY_ONE);
if (IsKeyPressed(KEY_KP_2)) nk_input_unicode(ctx, KEY_TWO);
if (IsKeyPressed(KEY_KP_3)) nk_input_unicode(ctx, KEY_THREE);
if (IsKeyPressed(KEY_KP_4)) nk_input_unicode(ctx, KEY_FOUR);
if (IsKeyPressed(KEY_KP_5)) nk_input_unicode(ctx, KEY_FIVE);
if (IsKeyPressed(KEY_KP_6)) nk_input_unicode(ctx, KEY_SIX);
if (IsKeyPressed(KEY_KP_7)) nk_input_unicode(ctx, KEY_SEVEN);
if (IsKeyPressed(KEY_KP_8)) nk_input_unicode(ctx, KEY_EIGHT);
if (IsKeyPressed(KEY_KP_9)) nk_input_unicode(ctx, KEY_NINE);
if (IsKeyPressed(KEY_KP_DECIMAL)) nk_input_unicode(ctx, KEY_PERIOD);
if (IsKeyPressed(KEY_KP_DIVIDE)) nk_input_unicode(ctx, KEY_SLASH);
if (IsKeyPressed(KEY_KP_MULTIPLY)) nk_input_unicode(ctx, 48);
if (IsKeyPressed(KEY_KP_SUBTRACT)) nk_input_unicode(ctx, 45);
if (IsKeyPressed(KEY_KP_ADD)) nk_input_unicode(ctx, 43);
}
/**
* Update the Nuklear context for the mouse input from raylib.
*
* @param ctx The nuklear context.
*
* @internal
*/
NK_API void nk_raylib_input_mouse(struct nk_context * ctx)
{
const float scale = GetNuklearScaling(ctx);
const int mouseX = (int)((float)GetMouseX() / scale);
const int mouseY = (int)((float)GetMouseY() / scale);
nk_input_motion(ctx, mouseX, mouseY);
nk_input_button(ctx, NK_BUTTON_LEFT, mouseX, mouseY, IsMouseButtonDown(MOUSE_LEFT_BUTTON));
nk_input_button(ctx, NK_BUTTON_RIGHT, mouseX, mouseY, IsMouseButtonDown(MOUSE_RIGHT_BUTTON));
nk_input_button(ctx, NK_BUTTON_MIDDLE, mouseX, mouseY, IsMouseButtonDown(MOUSE_MIDDLE_BUTTON));
// Mouse Wheel
float mouseWheel = GetMouseWheelMove();
if (mouseWheel != 0.0f) {
struct nk_vec2 mouseWheelMove;
mouseWheelMove.x = 0.0f;
mouseWheelMove.y = mouseWheel;
nk_input_scroll(ctx, mouseWheelMove);
}
}
/**
* Update the Nuklear context for raylib's state.
*
* @param ctx The nuklear context to act upon.
*/
NK_API void
UpdateNuklear(struct nk_context * ctx)
{
// Update the time that has changed since last frame.
ctx->delta_time_seconds = GetFrameTime();
// Update the input state.
nk_input_begin(ctx);
{
nk_raylib_input_mouse(ctx);
nk_raylib_input_keyboard(ctx);
}
nk_input_end(ctx);
}
/**
* Unload the given Nuklear context, along with all internal raylib textures.
*
* @param ctx The nuklear context.
*/
NK_API void
UnloadNuklear(struct nk_context * ctx)
{
struct nk_user_font* userFont;
// Skip unloading if it's not set.
if (ctx == NULL) {
return;
}
// Unload the font.
userFont = (struct nk_user_font*)ctx->style.font;
if (userFont != NULL) {
// Clear the raylib Font object.
void* fontPtr = userFont->userdata.ptr;
if (fontPtr != NULL) {
MemFree(fontPtr);
}
// Clear the user font.
MemFree(userFont);
ctx->style.font = NULL;
}
// Unload the custom user data.
if (ctx->userdata.ptr != NULL) {
MemFree(ctx->userdata.ptr);
}
// Unload the nuklear context.
nk_free(ctx);
TraceLog(LOG_INFO, "NUKLEAR: Unloaded GUI");
}
/**
* Convert the given Nuklear rectangle to a raylib Rectangle.
*/
NK_API struct
Rectangle RectangleFromNuklear(struct nk_context* ctx, struct nk_rect rect)
{
float scaling = GetNuklearScaling(ctx);
Rectangle output;
output.x = rect.x * scaling;
output.y = rect.y * scaling;
output.width = rect.w * scaling;
output.height = rect.h * scaling;
return output;
}
/**
* Convert the given raylib Rectangle to a Nuklear rectangle.
*/
NK_API struct
nk_rect RectangleToNuklear(struct nk_context* ctx, Rectangle rect)
{
float scaling = GetNuklearScaling(ctx);
return nk_rect(rect.x / scaling, rect.y / scaling, rect.width / scaling, rect.height / scaling);
}
/**
* Convert the given raylib texture to a Nuklear image
*/
NK_API struct nk_image TextureToNuklear(Texture tex)
{
// Declare the img to store data and allocate memory
// For the texture
struct nk_image img;
struct Texture* stored_tex = (struct Texture*)MemAlloc(sizeof(Texture));
// Copy the data from the texture given into the new texture
stored_tex->id = tex.id;
stored_tex->width = tex.width;
stored_tex->height = tex.height;
stored_tex->mipmaps = tex.mipmaps;
stored_tex->format = tex.format;
// Initialize the nk_image struct
img.handle.ptr = stored_tex;
img.w = (nk_ushort)stored_tex->width;
img.h = (nk_ushort)stored_tex->height;
return img;
}
/**
* Convert the given Nuklear image to a raylib Texture
*/
NK_API struct Texture TextureFromNuklear(struct nk_image img)
{
// Declare texture for storage
// And get back the stored texture
Texture tex;
Texture* stored_tex = (Texture*)img.handle.ptr;
// Copy the data from the stored texture to the texture
tex.id = stored_tex->id;
tex.width = stored_tex->width;
tex.height = stored_tex->height;
tex.mipmaps = stored_tex->mipmaps;
tex.format = stored_tex->format;
return tex;
}
/**
* Load a Nuklear image directly
*
* @param path The path to the image
*/
NK_API struct nk_image LoadNuklearImage(const char* path)
{
return TextureToNuklear(LoadTexture(path));
}
/**
* Unload a loaded Nuklear image
*
* @param img The Nuklear image to unload
*/
NK_API void UnloadNuklearImage(struct nk_image img)
{
Texture tex = TextureFromNuklear(img);
UnloadTexture(tex);
CleanupNuklearImage(img);
}
/**
* Cleans up memory used by a Nuklear image
* Does not unload the image.
*
* @param img The Nuklear image to cleanup
*/
NK_API void CleanupNuklearImage(struct nk_image img)
{
MemFree(img.handle.ptr);
}
/**
* Sets the scaling of the given Nuklear context.
*
* @param ctx The nuklear context.
* @param scaling How much scale to apply to the graphical user interface.
*/
NK_API void SetNuklearScaling(struct nk_context * ctx, float scaling)
{
if (ctx == NULL) {
return;
}
if (scaling <= 0.0f) {
TraceLog(LOG_WARNING, "NUKLEAR: Cannot set scaling to be less than 0");
return;
}
struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
if (userData != NULL) {
userData->scaling = scaling;
}
}
/**
* Retrieves the scale value of the given Nuklear context.
*
* @return The scale value that had been set for the Nuklear context. 1.0f is the default scale value.
*/
NK_API float GetNuklearScaling(struct nk_context * ctx)
{
if (ctx == NULL) {
return 1.0f;
}
struct NuklearUserData* userData = (struct NuklearUserData*)ctx->userdata.ptr;
if (userData != NULL) {
return userData->scaling;
}
return 1.0f;
}
#ifdef __cplusplus
}
#endif
#endif // RAYLIB_NUKLEAR_IMPLEMENTATION_ONCE
#endif // RAYLIB_NUKLEAR_IMPLEMENTATION

View File

@ -0,0 +1,17 @@
# raylib-nuklear-test
add_executable(raylib-nuklear-test raylib-nuklear-test.c)
target_compile_options(raylib-nuklear-test PRIVATE -Wall -Wextra -Wconversion -Wsign-conversion)
target_link_libraries(raylib-nuklear-test PUBLIC
raylib
raylib_nuklear
)
# Copy the resources
file(GLOB resources resources/*)
set(test_resources)
list(APPEND test_resources ${resources})
file(COPY ${test_resources} DESTINATION "resources/")
# Set up the test
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
add_test(NAME raylib-nuklear-test COMMAND raylib-nuklear-test)

View File

@ -0,0 +1,316 @@
/**********************************************************************************************
*
* raylib-assert - Assertion library for raylib.
* https://github.com/robloach/raylib-assert
*
* Copyright 2021 Rob Loach (@RobLoach)
*
* DEPENDENCIES:
* raylib https://www.raylib.com/
*
* LICENSE: zlib/libpng
*
* raylib-assert is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software:
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RAYLIB_ASSERT_H
#define RAYLIB_ASSERT_H
#ifdef __cplusplus
extern "C" {
#endif
// How to report failed assertions
#ifndef RAYLIB_ASSERT_LOG
/**
* The Trace Log Level used to report to TraceLog() on failed assertions. Defaults to LOG_FATAL.
*
* @example
* #define RAYLIB_ASSERT_LOG LOG_WARNING
*
* @see TraceLogLevel
*/
#define RAYLIB_ASSERT_LOG LOG_FATAL
#endif
// Define NDEBUG or RAYLIB_ASSERT_NDEBUG to skip assertions
#ifdef NDEBUG
#ifndef RAYLIB_ASSERT_NDEBUG
#define RAYLIB_ASSERT_NDEBUG
#endif
#endif
// Variadic Arguments
#define RAYLIB_ASSERT_CAT( A, B ) A ## B
#define RAYLIB_ASSERT_SELECT( NAME, NUM ) RAYLIB_ASSERT_CAT( NAME ## _, NUM )
#define RAYLIB_ASSERT_GET_COUNT( _1, _2, _3, _4, _5, _6, _7, RAYLIB_ASSERT_COUNT, ... ) RAYLIB_ASSERT_COUNT
#define RAYLIB_ASSERT_VA_SIZE( ... ) RAYLIB_ASSERT_GET_COUNT( __VA_ARGS__, 7, 6, 5, 4, 3, 2, 1 )
#define RAYLIB_ASSERT_VA_SELECT( NAME, ... ) RAYLIB_ASSERT_SELECT( NAME, RAYLIB_ASSERT_VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)
/**
* Assert whether the given condition is true.
*
* @param condition The condition that is expected to be true.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
* @param p5 (Optional) The fifth parameter in the message.
*/
#define Assert(...) RAYLIB_ASSERT_VA_SELECT(Assert, __VA_ARGS__)
/**
* Assert whether the two given parameters are equal.
*
* @param actual The actual value.
* @param expected The expected value.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
*/
#define AssertEqual(...) RAYLIB_ASSERT_VA_SELECT(AssertEqual, __VA_ARGS__)
/**
* Assert whether the given condition is false.
*
* @param condition The condition that is expected to be false.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
* @param p5 (Optional) The fifth parameter in the message.
*/
#define AssertNot(...) RAYLIB_ASSERT_VA_SELECT(AssertNot, __VA_ARGS__)
/**
* Assert whether the two given parameters are not equal.
*
* @param actual The actual value.
* @param notexpected The expected value that shouldn't equal the actual value.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
*/
#define AssertNotEqual(...) RAYLIB_ASSERT_VA_SELECT(AssertNotEqual, __VA_ARGS__)
/**
* Sets a failed assertion, with the given message.
*
* @param message (Optional) The message to provide for the failed assertion.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
* @param p5 (Optional) The fifth parameter in the message.
* @param p6 (Optional) The sixth parameter in the message.
*/
#define AssertFail(...) RAYLIB_ASSERT_VA_SELECT(AssertFail, __VA_ARGS__)
/**
* Assert whether an image is loaded.
*
* @param image The image to check for valid data.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
* @param p5 (Optional) The fifth parameter in the message.
*/
#define AssertImage(...) RAYLIB_ASSERT_VA_SELECT(AssertImage, __VA_ARGS__)
/**
* Assert whether two images are the same.
*
* @param image1 The first image to check is equal to the second.
* @param image2 The second image to check is equal to the first.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
*/
#define AssertImageSame(...) RAYLIB_ASSERT_VA_SELECT(AssertImageSame, __VA_ARGS__)
/**
* Assert whether two colors are the same.
*
* @param color1 The first color to check.
* @param color2 The second color to check.
* @param message (Optional) The message to provide on failed assertions.
* @param p1 (Optional) The first parameter in the message.
* @param p2 (Optional) The second parameter in the message.
* @param p3 (Optional) The third parameter in the message.
* @param p4 (Optional) The fourth parameter in the message.
*/
#define AssertColorSame(...) RAYLIB_ASSERT_VA_SELECT(AssertColorSame, __VA_ARGS__)
// Assert()
#ifdef RAYLIB_ASSERT_NDEBUG
#define Assert_1(condition)
#define Assert_2(condition, message)
#define Assert_3(condition, message, p1)
#define Assert_4(condition, message, p1, p2)
#define Assert_5(condition, message, p1, p2, p3)
#define Assert_6(condition, message, p1, p2, p3, p4)
#define Assert_7(condition, message, p1, p2, p3, p4, p5)
#else
#define Assert_1(condition) Assert_2(condition, #condition)
#define Assert_2(condition, message) do { if (!((bool)(condition))) { TraceLog(RAYLIB_ASSERT_LOG, "ASSERT: %s (%s:%i)", message, __FILE__, __LINE__); } } while(0)
#define Assert_3(condition, message, p1) Assert_2(condition, TextFormat(message, p1))
#define Assert_4(condition, message, p1, p2) Assert_2(condition, TextFormat(message, p1, p2))
#define Assert_5(condition, message, p1, p2, p3) Assert_2(condition, TextFormat(message, p1, p2, p3))
#define Assert_6(condition, message, p1, p2, p3, p4) Assert_2(condition, TextFormat(message, p1, p2, p3, p4))
#define Assert_7(condition, message, p1, p2, p3, p4, p5) Assert_2(condition, TextFormat(message, p1, p2, p3, p4, p5))
#endif
// AssertEqual()
#define AssertEqual_1(condition) Assert_2(condition, #condition)
#define AssertEqual_2(actual, expected) Assert_4((actual) == (expected), "AssertEqual(%s, %s) - Provided arguments are not equal", #actual, #expected)
#define AssertEqual_3(actual, expected, message) Assert_2((actual) == (expected), message)
#define AssertEqual_4(actual, expected, message, p1) Assert_3((actual) == (expected), message, p1)
#define AssertEqual_5(actual, expected, message, p1, p2) Assert_4((actual) == (expected), message, p1, p2)
#define AssertEqual_6(actual, expected, message, p1, p2, p3) Assert_5((actual) == (expected), message, p1, p2, p3)
#define AssertEqual_7(actual, expected, message, p1, p2, p3, p4) Assert_6((actual) == (expected), message, p1, p2, p3, p4)
// AssertNotEqual()
#define AssertNotEqual_1(condition) AssertNot_2(condition, #condition)
#define AssertNotEqual_2(actual, expected) Assert_4((actual) != (expected), "AssertNotEqual(%s, %s) - Provided arguments are equal", #actual, #expected)
#define AssertNotEqual_3(actual, expected, message) Assert_2((actual) != (expected), message)
#define AssertNotEqual_4(actual, expected, message, p1) Assert_3((actual) != (expected), message, p1)
#define AssertNotEqual_5(actual, expected, message, p1, p2) Assert_4((actual) != (expected), message, p1, p2)
#define AssertNotEqual_6(actual, expected, message, p1, p2, p3) Assert_5((actual) != (expected), message, p1, p2, p3)
#define AssertNotEqual_7(actual, expected, message, p1, p2, p3, p4) Assert_6((actual) != (expected), message, p1, p2, p3, p4)
// AssertNot()
#define AssertNot_1(condition) Assert_2(!(bool)(condition), #condition)
#define AssertNot_2(condition, message) Assert_2(!(bool)(condition), message)
#define AssertNot_3(condition, message, p1) Assert_3(!(bool)(condition), message, p1)
#define AssertNot_4(condition, message, p1, p2) Assert_4(!(bool)(condition), message, p1, p2)
#define AssertNot_5(condition, message, p1, p2, p3) Assert_5(!(bool)(condition), message, p1, p2, p3)
#define AssertNot_6(condition, message, p1, p2, p3, p4) Assert_6(!(bool)(condition), message, p1, p2, p3, p4)
#define AssertNot_7(condition, message, p1, p2, p3, p4, p5) Assert_7(!(bool)(condition), message, p1, p2, p3, p4, p5)
// AssertFail()
#ifdef RAYLIB_ASSERT_NDEBUG
#define AssertFail_0()
#define AssertFail_1(message)
#define AssertFail_2(message, p1)
#define AssertFail_3(message, p1, p2)
#define AssertFail_4(message, p1, p2, p3)
#define AssertFail_5(message, p1, p2, p3, p4)
#define AssertFail_6(message, p1, p2, p3, p4, p5)
#define AssertFail_7(message, p1, p2, p3, p4, p5, p6)
#else
#define AssertFail_0() TraceLog(RAYLIB_ASSERT_LOG, "ASSERT: AssertFail() (%s:%i)", __FILE__, __LINE__)
#define AssertFail_1(message) TraceLog(RAYLIB_ASSERT_LOG, "ASSERT: %s (%s:%i)", message, __FILE__, __LINE__)
#define AssertFail_2(message, p1) AssertFail_1(TextFormat(message, p1))
#define AssertFail_3(message, p1, p2) AssertFail_1(TextFormat(message, p1, p2))
#define AssertFail_4(message, p1, p2, p3) AssertFail_1(TextFormat(message, p1, p2, p3))
#define AssertFail_5(message, p1, p2, p3, p4) AssertFail_1(TextFormat(message, p1, p2, p3, p4))
#define AssertFail_6(message, p1, p2, p3, p4, p5) AssertFail_1(TextFormat(message, p1, p2, p3, p4, p5))
#define AssertFail_7(message, p1, p2, p3, p4, p5, p6) AssertFail_1(TextFormat(message, p1, p2, p3, p4, p5, p6))
#endif
// AssertImage()
#define AssertImage_0() AssertFail_1("No image provided for AssertImage()")
#define AssertImage_1(image) AssertNotEqual_4((image).data, 0, "AssertImage(%s) - Image not loaded", #image)
#define AssertImage_2(image, message) AssertNotEqual_3((image).data, 0, message)
#define AssertImage_3(image, message, p1) AssertNotEqual_4((image).data, 0, message, p1)
#define AssertImage_4(image, message, p1, p2) AssertNotEqual_5((image).data, 0, message, p1, p2)
#define AssertImage_5(image, message, p1, p2, p3) AssertNotEqual_6((image).data, 0, message, p1, p2, p3)
#define AssertImage_6(image, message, p1, p2, p3, p4) AssertNotEqual_7((image).data, 0, message, p1, p2, p3, p4)
// AssertTexture()
#define AssertTexture_0() AssertFail_1("No texture provided for AssertTexture()")
#define AssertTexture_1(texture) AssertNotEqual_4((texture).id, 0, "AssertTexture(%s) - Texture not loaded", #texture)
#define AssertTexture_2(texture, message) AssertNotEqual_3((texture).data, 0, message)
#define AssertTexture_3(texture, message, p1) AssertNotEqual_4((texture).data, 0, message, p1)
#define AssertTexture_4(texture, message, p1, p2) AssertNotEqual_5((texture).data, 0, message, p1, p2)
#define AssertTexture_5(texture, message, p1, p2, p3) AssertNotEqual_6((texture).data, 0, message, p1, p2, p3)
#define AssertTexture_6(texture, message, p1, p2, p3, p4) AssertNotEqual_7((texture).data, 0, message, p1, p2, p3, p4)
// AssertImageSame()
#ifdef RAYLIB_ASSERT_NDEBUG
#define AssertImageSame_0()
#define AssertImageSame_1(image)
#define AssertImageSame_2(image1, image2)
#define AssertImageSame_3(image1, image2, message)
#define AssertImageSame_4(image1, image2, message, p1)
#define AssertImageSame_5(image1, image2, message, p1, p2,)
#define AssertImageSame_6(image1, image2, message, p1, p2, p3)
#define AssertImageSame_7(image1, image2, message, p1, p2, p3, p4)
#else
#define AssertImageSame_0() AssertFail_1("AssertImageSame(): No images provided to AssertImageSame(), expected 2")
#define AssertImageSame_1(image) AssertFail_1("Only one image provided for AssertImageSame()")
#define AssertImageSame_2(image1, image2) AssertImageSame_5(image1, image2, "AssertImageSame(%s, %s) - Images do not match", #image1, #image2)
#define AssertImageSame_3(image1, image2, message) do { \
if (image1.width != image2.width || image1.height != image2.height || image1.format != image2.format) { \
AssertFail_1(message); \
break; \
} \
Color* colors1 = LoadImageColors(image1); \
Color* colors2 = LoadImageColors(image2); \
bool failure = false; \
for (int i = 0; i < image1.width * image1.height; i++) { \
Color color1 = colors1[i]; \
Color color2 = colors2[i]; \
if (color1.r != color2.r || color1.g != color2.g || color1.b != color2.b || color1.a != color2.a) { \
failure = true; \
break; \
} \
} \
UnloadImageColors(colors1); \
UnloadImageColors(colors2); \
if (failure) { \
AssertFail_1(message); \
} \
} while(0)
#define AssertImageSame_4(image1, image2, message, p1) AssertImageSame_3(image1, image2, TextFormat(message, p1))
#define AssertImageSame_5(image1, image2, message, p1, p2) AssertImageSame_3(image1, image2, TextFormat(message, p1, p2))
#define AssertImageSame_6(image1, image2, message, p1, p2, p3) AssertImageSame_3(image1, image2, TextFormat(message, p1, p2, p3))
#define AssertImageSame_7(image1, image2, message, p1, p2, p3, p4) AssertImageSame_3(image1, image2, TextFormat(message, p1, p2, p3, p4))
#endif
// AssertColorSame()
#define AssertColorSame_0() AssertFail_1("Colors not provided to AssertColorSame()")
#define AssertColorSame_1(color) AssertFail_1("Expected two colors for AssertColorSame()")
#define AssertColorSame_2(color1, color2) AssertColorSame_5(color1, color2, "AssertColorSame(%s, %s) - Colors do not match", #color1, #color2)
#define AssertColorSame_3(color1, color2, message) do { \
if (color1.r != color2.r || color1.g != color2.g || color1.b != color2.b || color1.a != color2.a) { \
AssertFail_1(message); \
}\
} while (0)
#define AssertColorSame_4(color1, color2, message, p1) AssertColorSame_3(color1, color2, TextFormat(message, p1))
#define AssertColorSame_5(color1, color2, message, p1, p2) AssertColorSame_3(color1, color2, TextFormat(message, p1, p2))
#define AssertColorSame_6(color1, color2, message, p1, p2, p3) AssertColorSame_3(color1, color2, TextFormat(message, p1, p2, p3))
#define AssertColorSame_7(color1, color2, message, p1, p2, p3, p4) AssertColorSame_3(color1, color2, TextFormat(message, p1, p2, p3, p4))
#ifdef __cplusplus
}
#endif
#endif // RAYLIB_ASSERT_H

View File

@ -0,0 +1,107 @@
#include "raylib.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include "raylib-nuklear.h"
#include "raylib-assert.h"
int main(int argc, char *argv[]) {
// Initialization
SetTraceLogLevel(LOG_ALL);
TraceLog(LOG_INFO, "================================");
TraceLog(LOG_INFO, "raylib-nuklear-test");
TraceLog(LOG_INFO, "================================");
InitWindow(640, 480, "raylib-nuklear-tests");
Assert(IsWindowReady());
// Make sure we're running in the correct directory.
Assert(argc > 0);
const char* dir = GetDirectoryPath(argv[0]);
Assert(ChangeDirectory(dir));
// InitNuklear()
struct nk_context *ctx = InitNuklear(10);
Assert(ctx);
// Image
struct nk_image image = LoadNuklearImage("resources/test-image.png");
Assert(image.handle.ptr);
Texture texture = TextureFromNuklear(image);
Assert(texture.width > 0);
// UpdateNuklear()
UpdateNuklear(ctx);
// Nuklear GUI Code
// https://github.com/Immediate-Mode-UI/Nuklear/wiki/Window
if (nk_begin(ctx, "Nuklear", nk_rect(50, 50, 400, 400),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
nk_button_label(ctx, "Button");
nk_layout_row_static(ctx, 256, 256, 1);
nk_image(ctx, image);
}
nk_end(ctx);
// Render
BeginDrawing();
ClearBackground(RAYWHITE);
// DrawNuklear()
DrawNuklear(ctx);
EndDrawing();
// UnloadNuklearImage()
UnloadNuklearImage(image);
// UnloadNuklear()
UnloadNuklear(ctx);
// InitNuklearEx()
Font font = LoadFont("resources/anonymous_pro_bold.ttf");
ctx = InitNuklearEx(font, 25.0f);
Assert(ctx);
UnloadNuklear(ctx);
UnloadFont(font);
// RectangleFromNuklear()
{
ctx = NULL;
struct nk_rect rect = nk_rect(10, 20, 30, 40);
Rectangle rectangle = RectangleFromNuklear(ctx, rect);
AssertEqual(rect.x, rectangle.x);
AssertEqual(rect.y, rectangle.y);
AssertEqual(rect.w, rectangle.width);
AssertEqual(rect.h, rectangle.height);
}
// RectangleFromNuklear(), RectangleToNuklear(), with scaling
{
struct nk_rect rect = nk_rect(10, 20, 30, 40);
ctx = InitNuklear(10);
SetNuklearScaling(ctx, 2.0f);
float scaling = GetNuklearScaling(ctx);
AssertEqual(scaling, 2.0f, "Scaling was incorrectly set.");
Rectangle rectangle = RectangleFromNuklear(ctx, rect);
AssertEqual(rect.x, rectangle.x / 2);
AssertEqual(rect.y, rectangle.y / 2);
AssertEqual(rect.w, rectangle.width / 2);
AssertEqual(rect.h, rectangle.height / 2);
rectangle = (Rectangle){20, 40, 60, 80};
rect = RectangleToNuklear(ctx, rectangle);
AssertEqual(rect.x, rectangle.x / 2);
AssertEqual(rect.y, rectangle.y / 2);
AssertEqual(rect.w, rectangle.width / 2);
AssertEqual(rect.h, rectangle.height / 2);
UnloadNuklear(ctx);
}
CloseWindow();
TraceLog(LOG_INFO, "================================");
TraceLog(LOG_INFO, "raylib-nuklear tests succesful");
TraceLog(LOG_INFO, "================================");
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

28
code/vendors/zpl.h vendored
View File

@ -34,7 +34,10 @@ GitHub:
https://github.com/zpl-c/zpl
Version History:
18.1.1 - fix zpl sort procs
18.1.4 - fix zpl_random_gen_isize/zpl_random_range_isize 32bit overflow
18.1.3 - set parent to parsed JSON nodes
18.1.2 - fix zpl sort procs
18.1.1 - updated table _clear method
18.1.0 - added table _clear method
18.0.4 - fix memory arena alignment & added tests
18.0.3 - fix emscripten support
@ -407,7 +410,7 @@ License:
#define ZPL_VERSION_MAJOR 18
#define ZPL_VERSION_MINOR 1
#define ZPL_VERSION_PATCH 2
#define ZPL_VERSION_PATCH 4
#define ZPL_VERSION_PRE ""
// file: zpl_hedley.h
@ -1202,20 +1205,27 @@ License:
#if defined(ZPL_DIAGNOSTIC_PUSH)
# undef ZPL_DIAGNOSTIC_PUSH
#endif
#if defined(ZPL_DIAGNOSTIC_PUSH_WARNLEVEL)
# undef ZPL_DIAGNOSTIC_PUSH_WARNLEVEL
#endif
#if defined(ZPL_DIAGNOSTIC_POP)
# undef ZPL_DIAGNOSTIC_POP
#endif
#if defined(__clang__)
# define ZPL_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
# define ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(x)
# define ZPL_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
#elif ZPL_INTEL_VERSION_CHECK(13,0,0)
# define ZPL_DIAGNOSTIC_PUSH _Pragma("warning(push)")
# define ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(x)
# define ZPL_DIAGNOSTIC_POP _Pragma("warning(pop)")
#elif ZPL_GCC_VERSION_CHECK(4,6,0)
# define ZPL_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
# define ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(x)
# define ZPL_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
#elif ZPL_MSVC_VERSION_CHECK(15,0,0)
# define ZPL_DIAGNOSTIC_PUSH __pragma(warning(push))
# define ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(x) __pragma(warning(push, x))
# define ZPL_DIAGNOSTIC_POP __pragma(warning(pop))
#elif ZPL_ARM_VERSION_CHECK(5,6,0)
# define ZPL_DIAGNOSTIC_PUSH _Pragma("push")
@ -11724,7 +11734,11 @@ License:
zpl_isize zpl_random_gen_isize(zpl_random *r) {
#if defined(ZPL_ARCH_32_BIT)
zpl_u32 u = zpl_random_gen_u32(r);
#else
zpl_u64 u = zpl_random_gen_u64(r);
#endif
zpl_isize i;
zpl_memcopy(&i, &u, zpl_size_of(u));
return i;
@ -11742,7 +11756,11 @@ License:
}
zpl_isize zpl_random_range_isize(zpl_random *r, zpl_isize lower_inc, zpl_isize higher_inc) {
#if defined(ZPL_ARCH_32_BIT)
zpl_u32 u = zpl_random_gen_u32(r);
#else
zpl_u64 u = zpl_random_gen_u64(r);
#endif
zpl_isize diff = higher_inc-lower_inc+1;
u %= diff;
zpl_isize i;
@ -17556,6 +17574,7 @@ License:
if (*err_code != ZPL_JSON_ERROR_NONE) { return NULL; }
zpl_array_append(obj->nodes, elem);
zpl_array_end(obj->nodes)->parent = obj;
p = zpl__json_trim(p, false);
@ -17677,6 +17696,7 @@ License:
if (err_code && *err_code != ZPL_JSON_ERROR_NONE) { return NULL; }
zpl_array_append(obj->nodes, node);
zpl_array_end(obj->nodes)->parent = obj;
char *end_p = p; zpl_unused(end_p);
p = zpl__json_trim(p, true);
@ -17807,7 +17827,7 @@ License:
#else
if (1)
#endif
zpl_fprintf(f, "%c\n", o->type == ZPL_ADT_TYPE_OBJECT ? '{' : '[');
zpl_fprintf(f, "%c\n", o->type == ZPL_ADT_TYPE_OBJECT ? '{' : '[');
else
{
indent -= 4;
@ -17829,7 +17849,7 @@ License:
#ifndef ZPL_PARSER_DISABLE_ANALYSIS
if (!o->cfg_mode)
#endif
zpl_fprintf(f, "%c\n", o->type == ZPL_ADT_TYPE_OBJECT ? '}' : ']');
zpl_fprintf(f, "%c\n", o->type == ZPL_ADT_TYPE_OBJECT ? '}' : ']');
}
}