Giter Site home page Giter Site logo

immediate-mode-ui / nuklear Goto Github PK

View Code? Open in Web Editor NEW
8.5K 123.0 508.0 10.79 MB

A single-header ANSI C immediate mode cross-platform GUI library

Home Page: https://immediate-mode-ui.github.io/Nuklear/doc/index.html

Makefile 0.04% C 99.73% Python 0.17% Shell 0.03% Batchfile 0.03%
c gui nuklear single-header-lib single-header c89 imgui multiplatform header-only

nuklear's Introduction

Nuklear

This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.

Features

  • Immediate-mode graphical user interface toolkit
  • Single-header library
  • Written in C89 (ANSI C)
  • Small codebase (~18kLOC)
  • Focus on portability, efficiency and simplicity
  • No dependencies (not even the standard library if not wanted)
  • Fully skinnable and customizable
  • Low memory footprint with total control of memory usage if needed / wanted
  • UTF-8 support
  • No global or hidden state
  • Customizable library modules (you can compile and use only what you need)
  • Optional font baker and vertex buffer output
  • Documentation

Building

This library is self-contained in one single header file and can be used either in header-only mode or in implementation mode. The header-only mode is used by default when included and allows including this header in other headers and does not contain the actual implementation.

The implementation mode requires defining the preprocessor macro NK_IMPLEMENTATION in one .c/.cpp file before #includeing this file, e.g.:

#define NK_IMPLEMENTATION
#include "nuklear.h"

IMPORTANT: Every time you include "nuklear.h" you have to define the same optional flags. This is very important; not doing it either leads to compiler errors, or even worse, stack corruptions.

Gallery

screenshot screen screen2 node skinning gamepad

Example

/* init gui state */
struct nk_context ctx;
nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);

enum {EASY, HARD};
static int op = EASY;
static float value = 0.6f;
static int i =  20;

if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
    NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
    /* fixed widget pixel width */
    nk_layout_row_static(&ctx, 30, 80, 1);
    if (nk_button_label(&ctx, "button")) {
        /* event handling */
    }

    /* fixed widget window ratio width */
    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;

    /* custom widget pixel width */
    nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
    {
        nk_layout_row_push(&ctx, 50);
        nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
        nk_layout_row_push(&ctx, 110);
        nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
    }
    nk_layout_row_end(&ctx);
}
nk_end(&ctx);

example

Bindings

There are a number of nuklear bindings for different languages created by other authors. I cannot attest for their quality since I am not necessarily proficient in any of these languages. Furthermore there are no guarantee that all bindings will always be kept up to date:

Credits

Developed by Micha Mettke and every direct or indirect contributor to the GitHub.

Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barrett (public domain) Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).

Big thank you to Omar Cornut (ocornut@github) for his imgui library and giving me the inspiration for this library, Casey Muratori for handmade hero and his original immediate-mode graphical user interface idea and Sean Barrett for his amazing single-header libraries which restored my faith in libraries and brought me to create some of my own. Finally Apoorva Joshi for his single-header file packer.

License

------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Micha Mettke
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------

Reviewers guide

When reviewing pull request there are common things a reviewer should keep in mind.

Reviewing changes to src/* and nuklear.h:

  • Ensure C89 compatibility.
  • The code should work for several backends to an acceptable degree.
  • Check no other parts of nuklear.h are related to the PR and thus nothing is missing.
  • Recommend simple optimizations.
    • Pass small structs by value instead of by pointer.
    • Use local buffers over heap allocation when possible.
  • Check that the coding style is consistent with code around it.
    • Variable/function name casing.
    • Indentation.
    • Curly bracket ({}) placement.
  • Ensure that the contributor has bumped the appropriate version in clib.json and added their changes to the CHANGELOG.
  • Have at least one other person review the changes before merging.

Reviewing changes to demo/*, example/* and other files in the repo:

  • Focus on getting working code merged.
    • We want to make it easy for people to get started with Nuklear, and any demo and example improvements helps in this regard.
  • Use of newer C features, or even other languages is not discouraged.
    • If another language is used, ensure that the build process is easy to figure out.
  • Messy or less efficient code can be merged so long as these outliers are pointed out and easy to find.
  • Version shouldn't be bumped for these changes.
  • Changes that improves code to be more inline with nuklear.h are ofc always welcome.

nuklear's People

Contributors

0x0203 avatar aganm avatar bmuessig avatar ccawley2011 avatar crazybaboon avatar cxong avatar dexp avatar dumblob avatar fdb avatar frostkiwi avatar hejsil avatar keharriso avatar lockie avatar lundril avatar mattn avatar mgerhardy avatar mmozeiko avatar nielsbishere avatar ohjurot avatar opsjson avatar phoekz avatar puppy6000 avatar ricanteja avatar riri avatar robloach avatar ronaaron avatar vurtun avatar wheybags avatar ytsarko avatar yukyduky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nuklear's Issues

Compile issues with strict C++17

Strict C++17 (all warnings as errors), doesn't allow if with a constexpr expression in there. That's what if constexpr is for. This is an easy fix; only define the nk_memcpy & nk_memset implementations if they are used. I did it by adding a NK_DEF_MEMCPY and NK_DEF_MEMSET if the user didn't define theirs. And the check for if(sizeof(nk_draw_index)==2) should only happen ifndef NK_UINT_DRAW_INDEX.
Nielsbishere@d0c22eb
The branch above fixes it, but I don't know where those are located in the actual source (only the nuklear.h is modified).

commit "Fix bug where width padding was applied twice" regression

Hi @Hejsil ,

Apparently, commit 14dd68e "Fix bug where width padding was applied twice" introduces a regression in the code. To visualise the bug introduced in this commit:

1 - build the demo glfw_opengl3 and run it;

2 - Go to overview -> Widgets -> Combo -> Fist

Note all the items text, Pistol, Fist, Shotgun are all squashed to the left, without any spacing and with the first capital letter disappearing halfway:

Uploading Screenshot at 2020-03-10 21-14-20.png…

Ubuntu-Mate 18.04 - 64 bit.

Nuklear Cross integration

Hi. There is a library called Nuklear Cross which can help us to hide hardware/software differences from developer and just let him/her write platform independent application. Can this be integrated to Nuklear?
If yes you can get rid of demo folder replacing it with single demo file. Selecting target platform can be implemented as providing single -D to the compiler or including header file.

Can't put combo box in a pop-up window

If I have a combo box in a pop-up window, it will crash when I click on the combo box. The assertion is in the line NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); in the function nk_nonblock_begin (line 16912).
Is this the desired behavior? what other components can't be used in a pop-up window ?

Window always on top

Hello I'm wondering if it is possible to make the main window topmost and float on top of all other application windows?

Restore cursor position in nk_edit_string ?

Hi folks,

First time posting here, so first things first: thanks for this great project. I have been using it for a while and <3 it. But I ran into a small problem:

I am using a text edit filed (nk_edit_string) and am programmatically re-focusing it (nk_edit_focus). Works well, however the position of the cursor gets reset.

It would be great to have a flag for the nk_edit_string to make it remember its cursor position (I think there is none as of now). Sadly, my familiarity with nuklear's internals is very limited. I solved this by adding functions to get and set the cursor position (alexandervanrenen@c74da8a).

My question would be if this feature is of general interest: Is there a good way to already accomplish this? Would it be possible to add such a flag or use functions to set the cursor position?

Thanks,
Alex

Handling fonts

Currently not useful for me yet; but could potentially be an issue for other people or in the future.
If someone wants multiple fonts per text field or object, they'd have to set it per context as far as I've seen. Is there no better option? Like being able to specify parts of text that use different fonts?

Better windows functionality

Currently minimized windows can't be moved or unminimized or closed.
For me closed windows also stay behind, because I don't know if they have been closed from C++; is there a flag in nk_window I could check?

Rotate coordinate space

It's useful to be able to rotate the coordinate space; for example, when drawing an analog clock.

I don't see any support for that in NK; did I miss it, or is it simply not there?

Update links

There's a few broken links since moving to Immediate-Mode-UI. These include the build system which still tries to build the old repo.

nk_window_is_closed no working

vurtun/nuklear#266

line: 15769

/* ... */
layout->flags |= NK_WINDOW_HIDDEN;
layout->flags |= NK_WINDOW_CLOSED;
layout->flags &= ~NK_WINDOW_MINIMIZED; // new line
/* ... */

layout->flags |= NK_WINDOW_CLOSED;

nk_window_is_closed does not work for me, looking in the previous Issue I found that someone reported it but this was not implemented.

Tested and it works, please test and implement.

Create and Port Over Wiki

The previous wiki, even if sparse had screenshots and examples of how to use most things in nk, would be nice to have that moved over or one created for it to be expanded on. Visualizing was one of the hardest parts of using this toolkit, but after it's been smooth sailing.

9-slice/9-patch support for skinning

I'm currently using nuklear and needed support for 9-slice textures for buttons, windows, etc. I have modified a local clone of nuklear to add the required features and am curious as to whether or not there is any interest in having these features pushed upstream. If so, I can make a PR.

Event input code requires two renders?

So, I've encountered this problem specifically on the edit-box. It's in this code:

if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, bounds.x, bounds.y, bounds.w, bounds.h); }

Left-mouse-button must be clicked and currently held down for an edit-box to be made active (show the caret).

However, if in a single event pump I push both the left-mouse-button down and left-mouse-button up, ctx->input->mouse.buttons[0].down is 0 and ctx->input->mouse.buttons[0].clicked is 2, and the edit-box is never made active.

Speaking specifically about Windows, is there some guarantee that each cycle of the event loop will only receive once mouse button event? The demos appear to work, but my code is a little more complicated, and yet I think it's only a matter of timing that the demos work, and if the events were delivered a little more batch-like, the demos would also fail.

What am I missing here?

Each Enter or Backspace key press will repeat several times in GLFW.

I'm using GLFW 3.3 with GL3 backend under MacOS v10.15.1.

In TextEditor, each Enter or Backspace key press will generate several key press events which makes the TextEditor nearly unusable.

I compiled nuklear with below defines:

    NK_INCLUDE_FIXED_TYPES: 1
    NK_INCLUDE_STANDARD_IO: 1
    NK_INCLUDE_DEFAULT_ALLOCATOR: 1
    NK_INCLUDE_VERTEX_BUFFER_OUTPUT: 1
    NK_INCLUDE_FONT_BAKING: 1
    NK_INCLUDE_DEFAULT_FONT: 1
    NK_KEYSTATE_BASED_INPUT: 1

How to fix it?

Backend: GLUT

Hi, would it be possible to have a glut demo with nuklear?

Building demo/sdl_opengl3 with msys2 causes conflicting types for 'SDL_main'

Building demo/sdl_opengl3 with MSYS2 causes:

$ make
rm -f bin/demo.exe
cc main.c -std=c99 -pedantic -O2 -o bin/demo.exe -lmingw32 -lSDL2main -lSDL2 -lopengl32 -lm -lGLU32 -lGLEW32
In file included from C:/msys64/mingw64/include/SDL2/SDL.h:32,
                 from main.c:14:
main.c:73:5: error: conflicting types for 'SDL_main'
   73 | int main(void)
      |     ^~~~
In file included from C:/msys64/mingw64/include/SDL2/SDL.h:32,
                 from main.c:14:
C:/msys64/mingw64/include/SDL2/SDL_main.h:121:29: note: previous declaration of 'SDL_main' was here
  121 | extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]);
      |                             ^~~~~~~~
make: *** [Makefile:25: demo.exe] Error 1

It can be fixed adding arg params:

int main(void)

- int main(void)
+ int main(int argc, char * argv[])

Adding possability to use 64bit unsigned long long in nk_property_ull gui element

Using 32bit size signed is limited to [−2,147,483,647, +2,147,483,647] range.
It's not possible to have larger value than that in the current Nuklear.
Adding support for unsigned long long which is 64bit size will have [0, +18,446,744,073,709,551,615] range and open up more possibility for apps using Nuklear.
The function could be called nk_property_ull(struct nk_context *ctx, const char *name, unsigned long long min, unsigned long long *val, unsigned long long max, unsigned long long step, float inc_per_pixel).

Adding this function would require:

enum nk_property_kind {
    NK_PROPERTY_INT,
    NK_PROPERTY_FLOAT,
    NK_PROPERTY_DOUBLE,
+   NK_PROPERTY_ULL
};
union nk_property {
    int i;
    float f;
    double d;
+   unsigned long long ull;
};

We have to think about not overflowing signed or wrap around unsigned values. INT30-C INT32-C.

How to get TAB to navigate between edit widgets?

I've got a layout with labels on the left and edit controls on the right. Everything works nicely, but I want to be able to hit TAB (for instance) to move from one 'field' to the next.

What is the proper way to accomplish this?

Ability to hide dropdown for NK_TREE_NODE

NK_TREE_NODE doesn't contain any children in my implementation of a tree view. So I would like it to be possible to disable the dropdown functionality for them. E.g. NK_HIDDEN.

if (nk_tree_push_id(ctx, NK_TREE_TAB, "application", NK_MINIMIZED, 0)) {

	if (nk_tree_element_push_id(ctx, NK_TREE_NODE, "test", NK_HIDDEN, &dat.selected0, 0))
		nk_tree_element_pop(ctx);

	nk_tree_pop(ctx);
}

Three optimisation requests: 'window-moved?...

Three additional APIs can make things better for the programmer (and the UX):

  • nk_was_window_moved -- rather than storing the window bounds and comparing each render cycle, NK already knows when it moved a window. A simple flag (zeroed after being checked) would be useful
  • nk_was_window-resized -- same as above, but even more useful, since a lot of UX involves calculating bounds-- and if the window isn't resized, all that work can be eliminated
  • nk_event_count -- not all the backends (GLFW, anyone?) tell you if events were processed or not. An optimisation can be to not render if no events were received. Since NK knows when events occur, it makes sense for it to return a simple count of events since the last query.

How to create a gridview ?

If I want to create a grid interface like excel, how should I do it ?
I can approximate it by using nk_group with NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR flag but creating unique name for each group is a pain especially if the number of grid can change in runtime.

Display horizontal scrollbar in text editor

How can I get a horizontal scrollbar to appear for the text editor*?
It is a bit limiting to have to find the longest line, in order to be able to scroll across the full length...

horizontal_scroll


*I am not sure if text editor is the correct name... Looking at the 'overview.c' code, the "text editor" seems to be generated by nk_edit_string in the following lines:

nk_layout_row_static( ctx, 180, 278, 1 );

nk_edit_string(

	ctx,
	NK_EDIT_BOX,
	box_buffer,
	&box_len,
	512,
	nk_filter_default
);

Can I use Nuklear without baking font?

I mean I need dynamic font stash to add font glyph dynamicly.
The demo seems baking all characters with font size info.Which I don't need.

Think I will use multiple font and different font size.
For some font I just need some of the character,lets's say
Chapter 1 with font size 96.
Other dialogues font with font 24.And so on.no need for all.

Backend: Direct3D 12

I notice that nuklear hasn't had any development on a D3D12 implementation/example and was wondering if this will be worked on in the near future or not?
ImGUI has been working on a D3D12 Rendering implementation since early 2018 and it is currently in a pretty good state and works well.

It would be nice to see Nuklear also be able to render with D3D12.

nk_begin no window

/*
#define NK_IMPLEMENTATION
#define NK_INCLUDE_DEFAULT_ALLOCATOR //prevents having to manage memory allows us of nk_init_default
#define NK_INCLUDE_FONT_BAKING//allows for use of custom fonts with high level API
#define NK_INCLUDE_DEFAULT_FONT//to allow loading default fon
#define NK_INCLUDE_STANDARD_IO//to allowloading custom fonts
#define _CRT_SECURE_NO_WARNINGS allows importing fonts without errors
*/

#include "Resource.h"
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <string>
#include <stdio.h>
#include <iostream>

#include <nuklear.h>





int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	struct nk_context ctx;
	nk_font_atlas atlas;
	struct nk_font_config cfg = nk_font_config(0);
	struct nk_font* font_14;
	cfg.oversample_h = 3;
	cfg.oversample_v = 2;
	cfg.coord_type = NK_COORD_PIXEL;
	const void* image;
	void* image2;
	int w, h;
	nk_font_atlas_init_default(&atlas);
	nk_font_atlas_begin(&atlas);
	//font_14 = nk_font_atlas_add_default(&atlas, 14, &cfg);
	font_14 = nk_font_atlas_add_from_file(&atlas, "Roboto-Light.ttf", 12, &cfg);
	image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_ALPHA8);
	image2 = new char[w * h];
	memcpy(image2, image, w * h);
	nk_font_atlas_end(&atlas, nk_handle_id(30), NULL); //30 means nothing?
	nk_init_default(&ctx, &font_14->handle);



	if (nk_begin(&ctx, "Window 1", nk_rect(10, 10, 400, 600), NK_WINDOW_BORDER | NK_WINDOW_MOVABLE)) {
	}
	nk_end(&ctx);
}

The definitions commented at the start have been added within the pre-compiler settings

Am I mistaken in that the above is the minimum required code to create a window? Since it doesn't work :( Are there minimalized examples for simple things like this?

Backend: macOS/iOS "Metal" port

Being able to have a version run using the native "Metal" API on macOS/iOS would be extremely helpful, as I'm migrating my tool from using the JUCE library, and I would greatly prefer to not rely on "glfw".

If someone has already done something along these lines, please inform me; Google didn't turn up anything useful.

ISO C90 compilation error (gcc)

twaik@ubuntu:~/Nuklear/demo/x11_rawfb$ make
rm -f bin/zahnrad 
cc main.c -std=c89 -pedantic -O2 -Wunused -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L -o bin/zahnrad -lX11 -lXext -lm
In file included from main.c:49:0:
../../nuklear.h: In function ‘nk_font_bake’:
../../nuklear.h:12902:17: error: C++ style comments are not allowed in ISO C90
                 // Need to zero this, or it will carry over from a previous
                 ^
../../nuklear.h:12902:17: error: (this will be reported only once per input file)

twaik@ubuntu:~/Nuklear/demo/x11_rawfb$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

NK_BUTTON_REPEATER does nothing

Setting the button behavior to NK_BUTTON_REPEATER, doesn't do anything different from NK_BUTTON_DEFAULT.

I'm assuming it's supposed to repeat as long as the button is pressed?

How to draw images with rawfb?

I am trying out Nuklear on a raw frame buffer (boot loader environment - U-Boot).

I can see examples of how to create an nk_image and draw it for openGL, but I cannot figure out how it works with nuklear_rawfb.h

It seems to draw fonts but I am not sure how to make it draw images. Is there an example?

X11 scrolling of images with clip region

Hello there!
I have met some issue with scrolling of images with active clip region. It is looks like that:

Initial state:
step-a

After scrolling a bit, image will overlap window menu bar.
step-b

This effect is absent if there is no clip region defined:
step-c

Is it issue with x11 backend or nuklear internals?

Chinese font rendering is blurring.

截屏2019-12-19下午5 13 16

English font rendering is pretty good. But Chinese character rendering is blurring.

I tried to set the oversimple other than 1, I got black squares.

截屏2019-12-19下午5 15 39

Items with same label have same values

If you duplicate the same window but give it a different name; it should function independently of the other window. Instead, because labels are used in lookup, every value is changed simultaneously, this should at least take into account the parent of the item. It should also be possible to use multiple items in one window that are named the same.

Window creation on name

Since nk_windows are created & found based on name, this means they can't be renamed, if I'm correct. Only if you know the old name and set the name hash and name through the window obtained from begin with PR #35.

Is there a function for renaming that I'm missing?

Invalid hover detection when windows are touching

What?

When windows are pixel-perfect aligned one next to the other, the hover status isn't updated properly.

Minimum example

Replace the window in the default demo with the following:

if (nk_begin(ctx, "Demo1", nk_rect(100, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);
if (nk_begin(ctx, "Demo2", nk_rect(300, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);

nuklear-bug-report-bad
The left button doesn't react on hover.

When windows are spread apart by 1 or more pixels, hover works fine:

if (nk_begin(ctx, "Demo1", nk_rect(100, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);
if (nk_begin(ctx, "Demo2", nk_rect(300 + 1, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);

nuklear-bug-report-good

Suggested fix

The hover isn't updated, because windows are detected as intersecting each other:

/* activate window if hovered and no other window is overlapping this window */
inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
iter = win->next;
while (iter) {
struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
(!(iter->flags & NK_WINDOW_HIDDEN)))
break;
if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
iter->popup.win->bounds.x, iter->popup.win->bounds.y,
iter->popup.win->bounds.w, iter->popup.win->bounds.h))
break;
iter = iter->next;
}
}

The NK_INTERSECT is defined as:

Nuklear/src/nuklear.h

Lines 5405 to 5406 in adc52d7

#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
(!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))

I'd suggest to fix the off-by-one error by making the upper bound exclusive:

#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
    (!(((x1 >= (x0 + w0)) || ((x1 + w1) <= x0) || (y1 >= (y0 + h0)) || (y1 + h1) <= y0)))

This way, it would match all the other checks based on NK_BETWEEN which is also exclusive in the upper bound:

Nuklear/src/nuklear.h

Lines 5402 to 5404 in adc52d7

#define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
#define NK_INBOX(px, py, x, y, w, h)\
(NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))

Image created in memory buffer triggers "if this triggers you forgot to add a font"

I am trying to modify a function called icon_load() that currently is responsible for loading a .png image into memory, into a function that simply loads an image buffer that is created in heap memory.

Here is the original source code for it, defined in example/extended.c:

static struct nk_image
icon_load(const char *filename)
{
    int x,y,n;
    GLuint tex;
    unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
    if (!data) die("[SDL]: failed to load image: %s", filename);

    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);
    return nk_image_id((int)tex);
}

Now, here is what I did to change icon_load() so that it loads image buffers instead of .png files:
Instead of generating an image buffer from a .png file, I generated a 4 x 4 texel GL_RGBA texture on heap memory. I basically replaced stbi_load() (which returns a pointer to stbi_uc just a typedef for unsigned char)
by malloc() (which returns a void pointer but it is cast to unsigned char). I have also replaced stbi_image_free() by free()):

static struct nk_image
icon_load(const char *filename)
{
    GLuint tex;
    
    unsigned char *data = (unsigned char*)malloc(64 * sizeof(char));
    static int messi = 1;    

    for (int i = 0; i < 64; i += 4)
    {   
        data[i + 0] = 4 * i;
        data[i + 1] = 0;
        data[i + 2] = 0;
        data[i + 3] = 0;
        printf("data[%d] = %d\n", i, data[i]);
    }   

    printf("Messi is %d\n", messi);
    messi++; 

    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    free(data);
    
    return nk_image_id((int)tex);
}

The output:

data[54] = 127
data[55] = 255
data[56] = 255Image created in memory triggers "if this triggers you forgot to add a font" 
data[57] = 127
data[58] = 255
data[59] = 127
data[60] = 255
data[61] = 127
data[62] = 255
data[63] = 127
Messi is 32
Segmentation fault (core dumped)

Looking at the output I assume that malloc() was successful.

The fact that Messi is now 32, indicates that icon_load() was successfully called 31 times for each of the icons/images in lines 821 - 829 , before any rendering was actually done.

Using good old printf() debugging I realised the crash occurs inside function nk_begin_titled() (located inside function basic_demo()):

NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");

How can this be fixed? How can I load images from memory buffer rather than a .png file?

PS: I have opened an issue on a now archived instance of nuklear, and I did get an answer from @revolucas, where he suggests the font has not been initialised. But it was, as NK_INCLUDE_DEFAULT_FONT is defined in the begining of the extended.c file and nk_style_set_font(ctx, &media->font_20->handle); is called just before nk_begin_titled().

symbol(s) not found for architecture x86_64

hi, im just testing out this framework. running on Mac OS 10.15, Xcode. Need plain English instructions in getting nuklear setup.

"symbol(s) not found for architecture x86_64". failed couple times in properly using the linker.

#include "nuklear.h"
#include <stdio.h>

enum {EASY, HARD};
static int op = EASY;
static float value = 0.6f;
static int i =  20;

struct nk_context ctx;
struct nk_user_font font;


void setup() {
    nk_init_default(&ctx, &font);

    if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
        NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
        // fixed widget pixel width
        nk_layout_row_static(&ctx, 30, 80, 1);
        if (nk_button_label(&ctx, "button")) {
            // event handling
        }
        // fixed widget window ratio width
        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;
        // custom widget pixel width
        nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
        {
            nk_layout_row_push(&ctx, 50);
            nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
            nk_layout_row_push(&ctx, 110);
            nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
        }
        nk_layout_row_end(&ctx);
    }


    nk_end(&ctx);

}



int main(int argc, const char * argv[]) {
    setup();
    
}

Undefined symbols for architecture x86_64:
  "_nk_begin", referenced from:
      _setup in main.o
  "_nk_button_label", referenced from:
      _setup in main.o
  "_nk_end", referenced from:
      _setup in main.o
  "_nk_init_default", referenced from:
      _setup in main.o
  "_nk_label", referenced from:
      _setup in main.o
  "_nk_layout_row_begin", referenced from:
      _setup in main.o
  "_nk_layout_row_dynamic", referenced from:
      _setup in main.o
  "_nk_layout_row_end", referenced from:
      _setup in main.o
  "_nk_layout_row_push", referenced from:
      _setup in main.o
  "_nk_layout_row_static", referenced from:
      _setup in main.o
  "_nk_option_label", referenced from:
      _setup in main.o
  "_nk_rect", referenced from:
      _setup in main.o
  "_nk_slider_float", referenced from:
      _setup in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Certain mouse events don't work

My guess is that point->box checks are broken, but it can also obviously also be my code.
The following work fine: sliders, progress bars. Trying to use anything else however, won't work correctly. Other things such as radio, push buttons, sliders and checkboxes don't work. Sliders however do work sometimes, but barely.
https://imgur.com/a/VQYFFRs
The code can be found at on my repo but can only be built on Windows with CMake.

NK code

enum { EASY, NORMAL, HARD };
static int op = EASY, active[3]{ 1, 0, 1 }, selected{};
static float value = 0.6f;
static int i =  20;
static usz test{};
List<const c8*> names = {
	"Cheese",
	"Peanuts"
};
if (nk_begin(ctx, "Show", nk_rect(50, 50, 220, 300),
			 NK_WINDOW_BORDER|NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
	// fixed widget pixel width
	nk_layout_row_static(ctx, 30, 80, 1);
	if (nk_button_label(ctx, "Button")) {
		oic::System::log()->debug("Hi");
	}
	// fixed widget window ratio width
	nk_layout_row_dynamic(ctx, 30, 2);
	if (nk_option_label(ctx, "Easy", op == EASY)) op = EASY;
	if (nk_option_label(ctx, "Normal", op == NORMAL)) op = NORMAL;
	if (nk_option_label(ctx, "Hard", op == HARD)) op = HARD;
	nk_layout_row_dynamic(ctx, 30, 2);
	nk_checkbox_label(ctx, "Yes?", active);
	nk_checkbox_label(ctx, "No?", active + 1);
	nk_checkbox_label(ctx, "Maybe?", active + 2);
	nk_layout_row_dynamic(ctx, 30, 2);
	nk_combobox(ctx, names.data(), int(names.size()), &selected, 30, nk_vec2(1, 1));
	// custom widget pixel width
	nk_layout_row_begin(ctx, NK_STATIC, 30, 2);
	{
		nk_layout_row_push(ctx, 50);
		nk_label(ctx, "Volume:", NK_TEXT_LEFT);
		nk_layout_row_push(ctx, 110);
		nk_slider_float(ctx, 0, &value, 1.0f, 0.1f);
		nk_progress(ctx, &test, 100, 1);
	}
	nk_layout_row_end(ctx);
}
nk_end(ctx);

Render code (after nk code)

if (!refresh && previous.data())
	refresh = previous.size() != ctx->memory.needed || memcmp(previous.data(), ctx->memory.memory.ptr, previous.size());

//Convert to draw data

if (refresh) {
	refresh = false;
	static const struct nk_draw_vertex_layout_element vertLayout[] = {
		{ NK_VERTEX_POSITION, NK_FORMAT_FLOAT,  vertexLayout[0].offset },
		{ NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, vertexLayout[1].offset },
		{ NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, vertexLayout[2].offset },
		{ NK_VERTEX_LAYOUT_END }
	};
	struct nk_convert_config cfg = {};
	cfg.shape_AA = NK_ANTI_ALIASING_ON;
	cfg.line_AA = NK_ANTI_ALIASING_ON;
	cfg.vertex_layout = vertLayout;
	cfg.vertex_size = vertexLayout.getStride();
	cfg.vertex_alignment = 4 /* Detect? */;
	cfg.circle_segment_count = 22;
	cfg.curve_segment_count = 22;
	cfg.arc_segment_count = 22;
	cfg.global_alpha = 1.0f;
	cfg.null = atlasTexture;
	nk_buffer cmds, verts, idx;
	nk_buffer_init(&cmds, &allocator, NK_BUFFER_DEFAULT_INITIAL_SIZE);
	nk_buffer_init(&verts, &allocator, NK_BUFFER_DEFAULT_INITIAL_SIZE);
	nk_buffer_init(&idx, &allocator, NK_BUFFER_DEFAULT_INITIAL_SIZE);
	nk_convert(ctx, &cmds, &verts, &idx, &cfg);
	vbo.release();
	ibo.release();
	primitiveBuffer.release();
	auto vboStart = (u8 *)verts.memory.ptr;
	auto iboStart = (u8 *)idx.memory.ptr;
	vbo = {
		g, NAME("NK VBO"),
		GPUBuffer::Info(Buffer(vboStart, vboStart + verts.needed), GPUBufferType::VERTEX, GPUMemoryUsage::LOCAL)
	};
	ibo = {
		g, NAME("NK IBO"),
		GPUBuffer::Info(Buffer(iboStart, iboStart + idx.needed), GPUBufferType::INDEX, GPUMemoryUsage::LOCAL)
	};
	primitiveBuffer = {
		g, NAME("Primitive buffer"),
		PrimitiveBuffer::Info(
			BufferLayout(vbo, vertexLayout),
			BufferLayout(ibo, BufferAttributes(GPUFormat::R16u))
		)
	};
	commands->clear();
	commands->add(
		BindPipeline(pipeline),
		SetClearColor(Vec4f { 0, 0.5, 1, 1 }),
		BeginFramebuffer(target),
		SetViewportAndScissor(),
		ClearFramebuffer(target),
		BindPrimitiveBuffer(primitiveBuffer),
		BindDescriptors(descriptors)
	);
	const nk_draw_command *cmd {};
	nk_draw_index offset {};
	nk_draw_foreach(cmd, ctx, &cmds) {
		if (!cmd->elem_count) continue;
		Texture t = Texture::Ptr(cmd->texture.ptr);
		auto r = cmd->clip_rect;
		commands->add(
			r.w == 16384 ? SetScissor() : SetScissor({ u32(r.w), u32(r.h) }, { i32(r.x), i32(r.y) }),
			DrawInstanced::indexed(cmd->elem_count, 1, offset)
		);
		offset += u16(cmd->elem_count);
	}
	commands->add(
		EndFramebuffer()
	);
	nk_buffer_free(&cmds);
	nk_buffer_free(&verts);
	nk_buffer_free(&idx);
	g.present(target, swapchain, commands);
	u8 *prev = (u8*)ctx->memory.memory.ptr;
	previous = Buffer(prev, prev + ctx->memory.needed);
} else
	g.present(target, swapchain);
//Reset
nk_clear(ctx);

Input events

//Receive events
nk_input_begin(ctx);
//Could potentially use a callback system for efficiency TODO:
bool processedMouse{};
for(auto *dvc : vi->devices)
	if (dvc->getType() == InputDevice::Type::KEYBOARD) {
		//Only loop through nuklear keys
		for (usz i = 0; i < NKey::count; ++i) {
			//Get our key
			String name = NKey::nameById(i);
			usz keyId = Key::idByName(name);
			if (keyId == Key::count) continue;
			//Send to NK
			auto state = dvc->getState(InputHandle(keyId));
			if (state == InputDevice::PRESSED)
				nk_input_key(ctx, nk_keys(NKey::values[i]), 1);
			else if (state == InputDevice::RELEASED)
				nk_input_key(ctx, nk_keys(NKey::values[i]), 0);
		}
	} else if(dvc->getType() == InputDevice::Type::MOUSE) {
		if (processedMouse) continue;
		f64 x = dvc->getCurrentAxis(MouseAxis::AXIS_X);
		f64 y = dvc->getCurrentAxis(MouseAxis::AXIS_Y);
		f64 px = dvc->getPreviousAxis(MouseAxis::AXIS_X);
		f64 py = dvc->getPreviousAxis(MouseAxis::AXIS_Y);
		if (px == x && py == y) continue;
		//Only loop through nuklear keys
		for (usz i = 0; i < NMouseButton::count; ++i) {
			//Get our key
			String name = NMouseButton::nameById(i);
			usz keyId = MouseButton::idByName(name);
			if (keyId == MouseButton::count) continue;
			nk_input_button(ctx, nk_buttons(i), int(x), int(y), int(dvc->getCurrentState(ButtonHandle(keyId))));
		}
		nk_input_motion(ctx, int(x), int(y));
		nk_input_scroll(ctx, nk_vec2(f32(dvc->getCurrentAxis(MouseAxis::AXIS_WHEEL)), 0));
		processedMouse = true;
	}
nk_input_end(ctx);

X11 Copy and Paste does not work

The copy and paste feature of the X11 demo does not work. The code (found in nuklear_xlib.h) that accesses the X11 clipboard seems to have all come from one commit (#371). Since then, there have been no substantial changes to the respective lines of code.

Copy and paste in the gdi equivalent works (nuklear_gdi.h), so the problem seems specific to the xlib implementation.

copy_paste

Window bounds

Is there a way to clamp scalable nk windows between a minimum and maximum size?
Also, I found that if you close your main window, it clears the vbo to 0 (expected), but then it resets it?

DX9 demo/d3d9nuklear_d3d9.h handle incorrectly resolution/window size

When the window size is different that the screen resolution and the window is maximixed this demo (DX9) handle incorrectly the resolution, for example the mouse hover is too far from where it should be, meaning you need to move the mouse to the left several centimeters or to the right to move the scroll bar. To replicate this compile the demo adding ShowWindow(wnd, SW_MAXIMIZE); in the main function and be sure the window width and height is different that the current screen resolution.
My guessing is that the function nk_d3d9_get_projection_matrix () is wrong, so the projection matrix is calculated incorrectly. Actually that function calculate the matrix in a no standard way, at least not in the normal way of normal D3D9 applications. Or is coded in a John Carmack's style, meaning hacking style.
I can't test D3d11 but I tested the gdi demo and it work correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.