nuklear dev ui + asset inspector tool
parent
d00ce4ec80
commit
72005402cf
|
@ -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)
|
||||
|
|
|
@ -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};
|
|
@ -1,4 +1,4 @@
|
|||
#include "debug/debug_replay.h"
|
||||
#include "dev/debug_replay.h"
|
||||
#include "core/camera.h"
|
||||
#include "models/entity.h"
|
||||
|
|
@ -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) {
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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;;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) },
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "debug/debug_draw.h"
|
||||
#include "dev/debug_draw.h"
|
||||
#include "models/entity.h"
|
||||
|
||||
void LeaveVehicle(ecs_iter_t *it) {
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
add_subdirectory(flecs)
|
||||
add_subdirectory(cwpack)
|
||||
add_subdirectory(raylib-nuklear)
|
||||
|
||||
add_library(vendors-bundle STATIC
|
||||
sfd.c
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
build
|
||||
.vscode
|
|
@ -0,0 +1,4 @@
|
|||
[submodule "vendor/nuklear"]
|
||||
path = vendor/nuklear
|
||||
url = https://github.com/Immediate-Mode-UI/Nuklear.git
|
||||
ignore = dirty
|
|
@ -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()
|
|
@ -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.
|
|
@ -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.
|
|
@ -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)
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 |
|
@ -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;
|
||||
}
|
|
@ -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.
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
|
@ -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
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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.
Binary file not shown.
After Width: | Height: | Size: 798 B |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue