Coder Social home page Coder Social logo

nuklear's Introduction

Nuklear

ALL DEVELOPMENT MOVED ELSEWHERE

Dear visitor,

this repository, issue tracker, etc. is abandoned in favor of https://github.com/Immediate-Mode-UI/Nuklear . Any activity in this issue tracker, any pull requests, etc. will be ignored.

Looking forward to hearing from you in https://github.com/Immediate-Mode-UI/Nuklear

Nuklear community

Build Status

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 and input handling but instead provides a very modular library approach by using 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 only focuses 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 memory control if needed or 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 to define 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 languges created by other authors. I cannot atest for their quality since I am not necessarily proficient in either 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 singe-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.
-----------------------------------------------------------------------------

nuklear's People

Contributors

0x0203 avatar antibluequirk avatar cosier avatar crazybaboon avatar cxong avatar dexp avatar diggit avatar dumblob avatar ettoretorti avatar fdb avatar fra-ktus avatar fredrikhson avatar hanna-kron avatar inolen avatar keharriso avatar mattn avatar mgerhardy avatar mmozeiko avatar molecularentropy avatar phoekz avatar ricanteja avatar rokups avatar rswinkle avatar siro20 avatar valera-rozuvan avatar vtorri avatar vurtun avatar waulfree avatar wheybags avatar ytsarko 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

Simple zahnrad Tutorial

Hi vurtun. You just direct messaged me (Krakenrad2) on twitter about using github to contact you.

I'll be brief:
-Right now I'm drawing my GUI to the SDL surface of my window (rendering text, bitmap buttons, mouse events, etc...)
-I would rather use zahnrad but the examples in the demo folder are very long.
-A simple tutorial on making the simple example below work in SDL would be good.
-I could make one, but I'm guessing it requires much more code to make it work with SDL.

Could you give me some general advice about what I should focus on to make the example below work in SDL?

Thanks.

Copy And Pasted Code:

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

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

struct zr_layout layout;
zr_begin(&ctx, &layout, "Show", zr_rect(50, 50, 220, 220),
ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_CLOSEABLE);
{
/* fixed widget pixel width /
zr_layout_row_static(&ctx, 30, 80, 1);
if (zr_button_text(&ctx, "button", ZR_BUTTON_DEFAULT)) {
/
event handling */
}

/* fixed widget window ratio width */
zr_layout_row_dynamic(&ctx, 30, 2);
if (zr_option(&ctx, "easy", op == EASY)) op = EASY;
if (zr_option(&ctx, "hard", op == HARD)) op = HARD;

/* custom widget pixel width */
zr_layout_row_begin(&ctx, ZR_STATIC, 30, 2);
{
    zr_layout_row_push(&ctx, 50);
    zr_label(&ctx, "Volume:", ZR_TEXT_LEFT);
    zr_layout_row_push(&ctx, 110);
    zr_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
}
zr_layout_row_end(&ctx);

}
zr_end(ctx);

MacOS build failed

MacOS demos build failing with:

demo.c:32:10: fatal error: 'GL/glew.h' file not found
#include <GL/glew.h>

Rendering differences

I think this would be better for a forum since I don't think it's really an issue, just a difference, but it's the only place were I can ask so here it is.

I have noticed some subtle differences in the GLFW and Allegro samples, I was wondering if it was possible to have a similar end result on GL (Allegro looks better, sharper in my opinion but opinions are subjective)

Check the uppercase E in node editor

Allegro:
screenshot 2016-02-25 20 02 35

GLFW:
screenshot 2016-02-25 20 02 39

It's very subtle but the colors look better and the fonts look better too.
We're using this for RetroArch as I mentioned before and I felt the text was a bit blurry.
screenshot 2016-02-25 20 08 09

zr_window_set_focus not working?

I have a menu item that is supposed to make a window focused (basically it's a window menu that will list all the open windows)

I am trying to achieve a sort of MDI interface and I want to use the Window menu to regain focus on windows that are on the background, so when I click Window->Demo Window
I'm doing zr_window_set_focus(ctx, "Demo Window"); but nothing really happens.

I also logged zr_window_has_focus on the Demo Window and it prints 1 so I don't really know what's going on.

screenshot 2016-03-02 02 08 56

Menu item alignment

In most interfaces, menus are left aligned, in zahnrad they are centered and it looks a bit weird.
I added my own method that makes the menu alignment configurable here:
libretro/RetroArch@1b1b596

Should I make a pull request or do you have a better idea than duplicating code like this?

all demos and examples fail in Ubuntu 14.04.3 32

Hi,
First of all I congratulate you on your innovative work. While I was looking for a gui toolkit apart from gtk, I found your project. I am impressed with the introductory animations. I wanted to try it.

I downloaded the zip package and exracted it in ~/Downloads folder. I navigated to ../zahnrad-master/demo/linuxgl and opened command prompt and run make

Here is the output

   kenn@kenn:~/Downloads/zahnrad-master/zahnrad-master/demo/linuxgl$ make 
 rm -f bin/zahnrad 
 gcc linuxgl.c ../../zahnrad.c -std=c89 -pedantic -O2 -o bin/zahnrad -lX11 -lm -lGL -lm -lGLU
 In file included from linuxgl.c:31:0:
 ../demo.c: In function ‘show_test_window’:
 ../demo.c:145:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
                  zr_progress(&menu, &prog, 100, ZR_MODIFIABLE);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:292:9: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
          zr_progress(&menu, &prog, 100, ZR_MODIFIABLE);
          ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:480:13: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
              zr_progress(&layout, &prog_value, 100, ZR_MODIFIABLE);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:582:13: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘size_t’ [-Wformat=]
              sprintf(buffer, "%lu", sum);
              ^
 ../demo.c:586:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
                  zr_progress(&combo, &x, 100, ZR_MODIFIABLE);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:587:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
                  zr_progress(&combo, &y, 100, ZR_MODIFIABLE);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:588:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
                  zr_progress(&combo, &z, 100, ZR_MODIFIABLE);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:589:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
                  zr_progress(&combo, &w, 100, ZR_MODIFIABLE);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:595:13: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘size_t’ [-Wformat=]
              sprintf(buffer, "%lu", sum);
              ^
 ../demo.c:644:27: warning: assignment from incompatible pointer type [enabled by default]
                  clip.copy = copy_callback;
                            ^
 ../demo.c:652:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[0], &text_len[0], 64, &text_active[0], &text_cursor[0], ZR_INPUT_DEFAULT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:652:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[0], &text_len[0], 64, &text_active[0], &text_cursor[0], ZR_INPUT_DEFAULT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:654:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[1], &text_len[1], 64, &text_active[1], &text_cursor[1], ZR_INPUT_DEC);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:654:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[1], &text_len[1], 64, &text_active[1], &text_cursor[1], ZR_INPUT_DEC);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:656:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[2], &text_len[2], 64, &text_active[2], &text_cursor[2], ZR_INPUT_FLOAT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:656:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[2], &text_len[2], 64, &text_active[2], &text_cursor[2], ZR_INPUT_FLOAT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:658:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[4], &text_len[4], 64, &text_active[4], &text_cursor[4], ZR_INPUT_HEX);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:658:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[4], &text_len[4], 64, &text_active[4], &text_cursor[4], ZR_INPUT_HEX);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:660:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[5], &text_len[5], 64, &text_active[5], &text_cursor[5], ZR_INPUT_OCT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:660:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[5], &text_len[5], 64, &text_active[5], &text_cursor[5], ZR_INPUT_OCT);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:662:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[6], &text_len[6], 64, &text_active[6], &text_cursor[6], ZR_INPUT_BIN);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:662:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[6], &text_len[6], 64, &text_active[6], &text_cursor[6], ZR_INPUT_BIN);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:672:17: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
                  zr_edit(&layout, buffer, &text_len[8], 64, &text_active[8], NULL, ZR_INPUT_DEFAULT);
                  ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:682:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[7], &text_len[7], 64, &text_active[7], &text_cursor[7], ZR_INPUT_ASCII);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 In file included from linuxgl.c:31:0:
 ../demo.c:682:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
              zr_edit(&layout, text[7], &text_len[7], 64, &text_active[7], &text_cursor[7], ZR_INPUT_ASCII);
              ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
       ^
 linuxgl.c: In function ‘font_bake_and_upload’:
 linuxgl.c:384:9: warning: passing argument 1 of ‘zr_font_bake_memory’ from incompatible pointer type [enabled by default]
          zr_font_bake_memory(&tmp_size, &glyph_count, &config, 1);
          ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:1513:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  void zr_font_bake_memory(zr_size *temporary_memory, int *glyph_count,
       ^
 linuxgl.c:390:9: warning: passing argument 1 of ‘zr_font_bake_pack’ from incompatible pointer type [enabled by default]
          if (!zr_font_bake_pack(&img_size, &img_width,&img_height,&custom,tmp,tmp_size,&config, 1))
          ^
 In file included from linuxgl.c:24:0:
 ../../zahnrad.h:1523:5: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
  int zr_font_bake_pack(zr_size *img_memory, int *img_width, int *img_height,
      ^
 linuxgl.c: In function ‘main’:
 linuxgl.c:845:17: warning: assignment from incompatible pointer type [enabled by default]
      alloc.alloc = mem_alloc;
                  ^
 linuxgl.c: In function ‘file_load’:
 linuxgl.c:206:10: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
      fread(buf, *siz, 1, fd);
           ^
 ../../zahnrad.c:110:13: error: size of array ‘zr__check_size’ is negative
  typedef int zr__check_size[(sizeof(void*) == sizeof(zr_size)) ? 1 : -1];
              ^
 ../../zahnrad.c: In function ‘zr_hash’:
 ../../zahnrad.c:514:5: warning: integer constant is too large for ‘unsigned long’ type [-Wlong-long]
      const zr_ulong m = 0xc6a4a7935bd1e995UL;
      ^
 In file included from ../../zahnrad.c:3278:0:
 ../../stb_truetype.h: In function ‘stbtt__rasterize_sorted_edges’:
 ../../stb_truetype.h:2048:4: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
     stbtt__hheap hh = { 0 };
     ^
 ../../zahnrad.c: In function ‘zr_begin’:
 ../../zahnrad.c:92:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  #define ZR_OFFSETOF(st, m) ((zr_size)(&((st *)0)->m))
                              ^
 ../../zahnrad.c:94:56: note: in expansion of macro ‘ZR_OFFSETOF’
      ((const type*)((const void*)((const zr_byte*)ptr - ZR_OFFSETOF(type, member))))
                                                         ^
 ../../zahnrad.c:6557:27: note: in expansion of macro ‘ZR_CONTAINER_OF_CONST’
                      cur = ZR_CONTAINER_OF_CONST(iter, struct zr_window, buffer);
                            ^
 make: *** [zahnrad] Error 1

I hope you help me work it.

Regards.

Kenn

Sample code not working?

Hey, I have many questions/comments about your sample code under the README. (this is all c++)

  1. Firstly it seems that the first line needs to be changed to this: struct gui_command_buffer *buffer = new gui_command_buffer; or else it doesn't work on this line:gui_foreach_command(cmd, buffer) {
  2. In reference to void *memory = malloc(MEMORY_SIZE); What is memory size? I noticed that in the demo it was set to 64 * 1024... what is the significance of this?
  3. In reference to len = gui_panel_edit(&layout, buffer, len, 256, &active, GUI_INPUT_DEFAULT); What is len? what is active?
  4. I have been trying for a very long time for your example to work but its always crashing on "gui_panel_begin" I have confirmed that the assert statements are returning properly, beyond that I didn't want to have to debug your code to see where it crashes. Do you think you could point me in the right direction here?

Errors

Hey! There are some errors when compiling the library right now in c++. Here are the errors:

Frame.cpp:(.text+0x1fc): undefined reference to zr_label' /tmp/ccJldMxt.o: In functionzr_tooltip':
zahnrad.c:(.text+0x311c7): undefined reference to `zr_text'
collect2: error: ld returned 1 exit status

Also your demo is off as well, should be zr_panel as opposed to zr_layout.

Thanks!

Minor: typo

ZR_POOL_DEFAULT_CAPACTIY -> ZR_POOL_DEFAULT_CAPACITY (I could not write it directly to the line using GitHub line comments feature, because the commit diff was huge and GitHub didn't show it)

Clicks registering while resizing

Don't know if this is a bug per-se or some error in my implementation, I tried to reproduce on the demos a lot and only managed once to get a click to register.
Basically it seems that resizing a window causes some unintended clics on some elements when you hover over them (or the place were the elements would be after resizing.

resize

May be related to this other issue? #54
I'll revert this
win->flags &= ~(zr_flags)ZR_WINDOW_ROM

In my code and do some more testing

Minimize / maximize is broken if windows overlap.

If a minimized window is on top of another one, the maximize button (as well as the close button) won't work. Probably because of:

if (!(layout->flags & ZR_WINDOW_ROM)) {

In zr_header_button.

If a maximized window is on top of another one and the minimize button is clicked, this window gets send to the background in the next run after releasing the mouse button with zr_input_button.

Cheers, richi

Issues

Hey! Thanks as always for fixing these issues so quickly. I've got a few more for you.

  1. On lines 4574 and 4575 looks like you are doing the following:

scroll.w = scroll.w;
scroll.x = scroll.x;

Were you trying to do something else?

  1. Doesn't demo.c need the following lines appended to the top?

define LEN(a) (sizeof(a)/sizeof(a)[0])

define UNUSED(a) ((void)(a))

include <stdarg.h>

include "zahnrad.h"

void clipboard_set(const char text){UNUSED(text);}
zr_bool clipboard_is_filled(void){return zr_false;}
const char
clipboard_get(void) {return NULL;}

I've found it doesn't compile without this (at least on Windows).

  1. Scroll bar is a little bit glitchy. It only scrolls up and down when the mouse is exactly over it. There should be a bit of wiggle room. I'd suggest the following logic:

bool flag = false;
if (mouse.clicked_on_Scrollbar()) { flag = true; }
if (flag && mouse.unclicked) { flag = false; }

if (flag) {
//scroll scroll bar distance mouse has moved in the y direction regardless of x
scrollbar.scroll(mouse.prev_x - mouse.curr_x);
}

  1. Backspace doesn't seem to work right (at least on the windows demo). When I click backspace (on demo.c, also important to note here that I did do a bunch of "ctrl" operations before I noticed the issue) it adds characters to the input box.

Anyways thanks for reading and I look forward to an update!

Sample code issues v2

Hey! Just wanted to list here some issues with your sample code:

"zr_combo(&context, items, LEN(items), &item, 20, &active);"
zr_combo isn't a function.

"zr_window_init(&window, 50, 50, 220, 180,
ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE,
&queue, &style, &input);"

This function actually requires a "zr_rect"

Just wanted to mention these! Thanks for all your hard work here.

Bug: possible call to free() on unallocated memory

Shouldn't the zr_tooltip_end() call be rather only in case some tooltip was created? In

    /* execute tooltip and fill with text */
    if (zr_tooltip_begin(ctx, &layout, (float)text_width)) {
        zr_layout_row_dynamic(ctx, (float)text_height, 1);
        zr_text(ctx, text, text_len, ZR_TEXT_LEFT);
    }
    zr_tooltip_end(ctx);

it seems to be quite dagerous. Solution might look like the following:

    /* execute tooltip and fill with text */
    if (zr_tooltip_begin(ctx, &layout, (float)text_width)) {
        zr_layout_row_dynamic(ctx, (float)text_height, 1);
        zr_text(ctx, text, text_len, ZR_TEXT_LEFT);
        zr_tooltip_end(ctx);
    }

I didn't check other similar places, but it's worth taking a careful look at.

UI recording and UI bytecode interpreter

As some may know I added the functionality to record UI and replay it at a later point of time some time ago. The main premise is that since the recorded UI is fixed allows for a lot more control like the ability to check if the UI needs to redrawn or even a lot more widget depended information. Internally this is achieved by serializing function call and parameter into a buffer that later can be executed again. State changes are signaled in contrast to the typical immediate mode API by using events while also providing an API to change the serialized widget state. So in the end not much is lost while a lot is achieved.

So far this would already allow things like an editor comparable to Qt but more powerful since dynamic widgets like combo boxes, charts or any highly dynamic UI code which are tedious to work with in classic retain mode APIs could be generated by recording or using the immediate mode API. So in theory this alone could be a huge win.

I thought about it a little more and I noticed that the step between just serializing widgets and a custom script language is not far fetched. I am not talking about bindings to other languages which can already be done, but something more aligned to shader languages in graphics APIs. The basic idea would be that the language (If it even could called that since it probably does not have to be turing complete) would call different widget just like you would with the default immediate mode API (which will still be usable like before) but would generate custom events as output (since you cannot directly access your program). So far example this script:

Script (pseudo code):

event changed_mouse_sensitivity {
    float value;
}
event mouse_sensitivity_greater_two {
    float value;
}

void main()
{
    s = slider("mouse_sensitivity", 0, 5, 10);
    if (s.isModified()) {
        event changed_mouse_sensitivity evt;
        evt.value = s.value;
        generateEvent(evt);
    }
    if (s.value > 2) {
        event mouse_sensitivity_greater_two evt;
        evt.value = s.value;
        generateEvent(evt);
    }
}

Native code:

/* register custom event types here */
zr_exec(...); /* run 'script' */

/* first way to check for changes */
zr_foreach_event(....) {
    if (evt.type == CUSTOM_EVENT_CHANGE_MOUSE_SENSITIVITY) {
        /* handle mouse sensitivity change */
    }      
}

/* second way to access and check for UI changes directly */
zr_element mouse_sensitivity = zr_lookup_string(program, "mouse_sensitivity");
if (zr_element_is_modified(mouse_sensitivity)) {
    /* handle mouse sensitivity change */
    zr_element_clear_modified(mouse_sensitivity);
}

So in script you would create a slider and check if the current slider value is greater than two and would generate a custom event if so. So in your native code you wouldn't have to check for each slider if it has been modified but instead you would only listen to custom events. It would be especially helpful for button events. In addition you could also access the widget by handle and check for changes directly as well. While this script could have logic like I described it could also just define each widget as data (used by editors) like so (still pseudo code):

begin("Demo")
layout_row_dynamic(30, 2);
slider("mouse_sensitivity", 0, 0.5, 1.0);
button("ok_button", "ok");
end()

So this would look more like the bytecode generated currently by recording and would just use default events for clicking, hovering, etc but could be extended by modifying the generated editor textual output to have custom events.

What I described up to this point would stand as three different APIs that would support each other. First the default immediate mode API which is the base for and runs everything. Then above that would be UI recording which allows to use the immediate mode API to turn dynamic frame based UI to a fixed bytecode UI script and with that more control and information and finally the bytecode script layer.

These three could be used interchangeably.
So for example you have an UI which means in most cases that most of its layout is quite fixed and is not required to change a lot but you still update and redraw it every frame. Instead you could turn that into script and run that from data.
Lets extend the use case and say your UI has a combo box which needs to be filled at the beginning of the program. In classical retain mode APIs you would have to fill a data structure and pass that to the combo box which is quite tedious for more advanced changes like removing and in using the immediate mode API you would have to call and redraw the combo box every frame.
Now in this case the recording API would become handy since it would generate the combo box for you at the beginning of the program and could then be combined with the fixed UI script.
Finally lets extend it a third time and say we have some highly dynamic data used for charts. In this case we would use the immediate mode API.

This is basically the high level idea I had. There are of course a lot of problem related to this like how to extend the script language with custom widgets, the best way to combine recorded and normal script, what script language with what syntax, what control statements should the language support, etc.

So finally I want to head to my question. I personally don't have much experience with languages I wrote an emulators once so I know a little bit how to write bytecode but I have no experience about if what I described could be or even should be done by using a script language. I suspect no since what the language would actually do is very limited it is barley more than just data. For example it wouldn't need functions or probably even variables and is therefore quite simple. I know for example that bitcoin uses a very basic interpreter for something related and I will take another look into that.

So for my question I would ask if what I am thinking about even made sense or is just over engineered bullshit that could be done by using a script language, should it even be done? or should the library stay simple and if it is worth it then if it should be done by only using bytecode inside the library and provide a way to generate the bytecode outside the library or since the language is so simple would even make sense to actually implement everything inside the library?
So in general feedback would be appreciated.

Enhancement: avoid static on non-const variables

Probably the last code-related thing I'm concerned with is the use of Zahnrad in multi-threaded applications, because some functions still contain non-const variables which are static (zr_draw_list_path_arc_to_fast(), zr_font_japanese_glyph_range(), zr_style_property(), zr_style_color()). It would be better to add them to some external state structure and/or to API.

Input box

Hey! The input box is still not working quite right, am I doing something wrong or has that not yet been perfected? In specific I cannot select my own index in the input box an make modifications. I am using the windows example. Thanks for taking a look!

Layout (x,y placement)

I noticed that widgets can be placed in a layout in the panel, but is there an option to add widgets at an x, y location? (and to specify width and height) Like sort of a null layout.

Can this feature be added? (or does it already exist?)

Thanks!

C89 violation

RetroArch tries to use C89 whenever is possible too, like zahnrad itself.
When testing a C89 build we got the following error:

zahnrad.c:10772:30: error: ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]

Might be something you want to look at since you're striving for C89 compatibility

Compiling with Clang LLVM ILP32 / LP64

Right now, compiling with Clang LLVM in 32 or 64 bit gives some minor type issues.

ZR_COMPILE_WITH_FIXED_TYPES 1

ILP32: zr__check_size failed.

LP64:
a lot of warnings (demo.c) because size_t* ('unsigned long * ') is incompatible to zr_size* ('unsigned long long *'). (stupid compiler...)

changing:

typedef uint64_t zr_size;

to:

typedef uintptr_t zr_size;

would solve 32 and 64 bit issues.

ZR_COMPILE_WITH_FIXED_TYPES 0

ILP32:
zr__check_ulong failed.

LP64:
No problems.

changing:

typedef unsigned long zr_ulong;

to:

typedef unsigned long long zr_ulong;

would solve 32 bit issues, without generating 64 bit ones :)

Cheers, richi

Endless loop in zr_user_font_glyphs_fitting_in_space

I have found a small glitch in zr_user_font_glyphs_fitting_in_space. It is easy to run into an endless loop, since glyph_len can get zero and there is no test for that in:

     while ((width <= space) && text_len) { 

I guess it should read:

    while ((width <= space) && text_en && glyph_len) {

Another problem can occur if offset is not getting incremented and the function therefore returns 0. This will result in an endless loop for example in zr_widget_edit_box.

Really great work!

Cheers, richi

Issues with graphics disappearing

Hey, I have the following code currently running:

#include "Utilities/Themis.h"

#define MEMORY_SIZE  (64 * 1024)

using namespace std;

Themis *main_controller;

zr_style style;
zr_user_font font;
zr_command_queue queue;
zr_window window;

enum {EASY, HARD};
zr_size option;
zr_float value;
struct zr_input input;

MouseInfo temp;

static zr_size font_get_text_width(zr_handle handle, const zr_char *t, zr_size l) {
    return main_controller->graphics_handle->getStringLength(t, l);
}

int main(int argc, char **argv) {
    main_controller = new Themis();
    main_controller->Init(argc, argv); //initializes everything for you
    //Frame frame(main_controller, 50, 50, 220, 180);
    
    font.userdata.ptr = this;
    font.height = 10;
    font.width = font_get_text_width;
    zr_style_default(&style, ZR_DEFAULT_ALL, &font);

    /* allocate memory to hold draw commands */
    zr_command_queue_init_fixed(&queue, malloc(MEMORY_SIZE), MEMORY_SIZE);

    /* initialize window */
    zr_window_init(&window, zr_rect(50, 50, 220, 180),
    ZR_WINDOW_BORDER,
    &queue, &style, &input);

    /* setup widget data */
    option = EASY;
    value = 0.6f;
    
    temp.x.data = 0;
    temp.y.data = 0;
    
    while (true) {
        //frame.handle_input();
        
        zr_input_begin(&input);
        // record input

        /*
        if (main_controller->mouseInfo.button.data == 0) {
                zr_input_button(&input, ZR_BUTTON_LEFT, main_controller->mouseInfo.x.data, main_controller->mouseInfo.y.data, zr_true);
        } else {
                zr_input_button(&input, ZR_BUTTON_LEFT, main_controller->mouseInfo.x.data, main_controller->mouseInfo.y.data, zr_false);
        }
        if (main_controller->mouseInfo.x.data != temp.x.data || main_controller->mouseInfo.y.data != temp.y.data) {
                zr_input_motion(&input, temp.x.data, temp.y.data);
                temp.x.data = main_controller->mouseInfo.x.data;
                temp.y.data = main_controller->mouseInfo.y.data;
        }

        if (main_controller->keyboardInfo.c != 0 && main_controller->keyboardInfo.state.data != 0)
                zr_input_char(&input, main_controller->keyboardInfo.c);
        else if (main_controller->keyboardInfo.code.data == 14)
                if (main_controller->keyboardInfo.state.data != 0)
                        zr_input_key(&input, ZR_KEY_BACKSPACE, zr_true);
                else
                        zr_input_key(&input, ZR_KEY_BACKSPACE, zr_false);
        */
        zr_input_end(&input);
        
        //frame.construct();
        
        zr_context context;
        zr_begin(&context, &window);
        const char *items[] = {"Fist", "Pistol", "Railgun", "BFG"};
        zr_header(&context, "Show", 0, 0, ZR_HEADER_LEFT);
        /*
        zr_layout_row_static(&context, 30, 80, 1);
        if (zr_button_text(&context, "button", ZR_BUTTON_DEFAULT)) {
            // event handling
        }
        zr_layout_row_dynamic(&context, 30, 2);
        if (zr_option(&context, "easy", option == EASY)) option = EASY;
        if (zr_option(&context, "hard", option == HARD)) option = HARD;
        zr_layout_row_begin(&context, ZR_STATIC, 30, 2);
        {
            zr_layout_row_push(&context, 50);
            zr_label(&context, "Volume:", ZR_TEXT_LEFT);
            zr_layout_row_push(&context, 110);
            value = zr_slider(&context, 0, value, 1.0f, 0.1f);
        }
        zr_layout_row_end(&context);
        */
        zr_end(&context, &window);
        
        //frame.draw();
        
        while (!main_controller->render) {}
        main_controller->graphics_handle->SetPriority(0); //just a formality, doesn't do anything considering the entire array is filled with -1
        fill_n(main_controller->graphics_handle->buffer_i, main_controller->screen_width.data * main_controller->screen_height.data, -1);
        const struct zr_command *cmd;
        Integer colorC;
        main_controller->graphics_handle->SetPriority(2);
        zr_foreach_command(cmd, &queue) {
            switch (cmd->type) {
                case ZR_COMMAND_SCISSOR: {
                const struct zr_command_scissor *s = zr_command(scissor, cmd);
                main_controller->graphics_handle->setClip(s->x, s->y, s->w, s->h);
                break;
                }
                case ZR_COMMAND_LINE: {
                const struct zr_command_line *l = zr_command(line, cmd);
                colorC.bytes[3] = 2; // setting priority
                colorC.bytes[0] = l->color.r;
                colorC.bytes[1] = l->color.g;
                colorC.bytes[2] = l->color.b;
                main_controller->graphics_handle->drawLine(l->begin.x, l->begin.y, l->end.x, l->end.y, colorC.data);
                break;
                }
                case ZR_COMMAND_RECT: {
                const struct zr_command_rect *r = zr_command(rect, cmd);
                colorC.bytes[3] = 2; // setting priority
                colorC.bytes[0] = r->color.r;
                colorC.bytes[1] = r->color.g;
                colorC.bytes[2] = r->color.b;
                main_controller->graphics_handle->fillSquare(r->x, r->y, r->w, r->h, colorC.data);
                break;
                }
                case ZR_COMMAND_CIRCLE: {
                const struct zr_command_circle *c = zr_command(circle, cmd);
                colorC.bytes[3] = 2; // setting priority
                colorC.bytes[0] = c->color.r;
                colorC.bytes[1] = c->color.g;
                colorC.bytes[2] = c->color.b;
                main_controller->graphics_handle->fillCircle(c->x + (c->w / 2), c->y + (c->w / 2), c->w / 2, colorC.data);
                break;
                }
                case ZR_COMMAND_TRIANGLE: {
                const struct zr_command_triangle *t = zr_command(triangle, cmd);
                colorC.bytes[3] = 2; // setting priority
                colorC.bytes[0] = t->color.r;
                colorC.bytes[1] = t->color.g;
                colorC.bytes[2] = t->color.b;
                Polygon tri;
                tri.addPoint(t->a.x, t->a.y);
                tri.addPoint(t->b.x, t->b.y);
                tri.addPoint(t->c.x, t->c.y);
                main_controller->graphics_handle->fillPolygon(tri, colorC.data);
                break;
                }
                case ZR_COMMAND_TEXT: {
                const struct zr_command_text *t = zr_command(text, cmd);
                main_controller->graphics_handle->drawString(t->string, t->x, t->y + 10, _WHITE);
                break;
                }
            }
        }
        main_controller->graphics_handle->setClip(-1, -1, -1, -1);
        main_controller->render = false;
        
        cout << "drew" << endl;
    }
    return 0;
}

Please make a note that most of the code is commented out. I have been looking through all of my code and I can't find anything wrong with it. Anyways the error here is that the window shows up for a very temporary time and then disappears. However the program itself does not crash. It's almost as if the algorithm just stops generating squares and such to generate. If you get a chance could you please take a look? I originally thought maybe the window was closing but closing is set to 0 in the header and input isn't even being processed. Thanks!

Password Hiding

Hi, is there is a way to hide text input as you type it in, in the same way when you enter passwords when logging into a website (for example)? If not, could you make a feature for this, or explain how one would make/do one?
Thanks a lot!

Question: Open/Close windows dynamically

On our project we will have several windows, settings, dialogs, etc.
Right now I have a sort of main function that controls everything:

static void zrmenu_frame(struct zrmenu *gui, int width, int height)
{
   struct zr_context *ctx = &gui->ctx;

   zrmenu_wnd_control(ctx, width, height, gui);   
   zrmenu_wnd_main(ctx, width, height, gui);
   zrmenu_wnd_demo(ctx, width, height, gui);

   zr_buffer_info(&gui->status, &gui->ctx.memory);
}

Actually opening a window later is not a problem, for instance I added a button to open wnd_control and then in my function I did this

static void zrmenu_frame(struct zrmenu *gui, int width, int height)
{
   struct zr_context *ctx = &gui->ctx;

   if (wnd_control)
      zrmenu_wnd_control(ctx, width, height, gui);   
   zrmenu_wnd_main(ctx, width, height, gui);
   zrmenu_wnd_demo(ctx, width, height, gui);

   zr_buffer_info(&gui->status, &gui->ctx.memory);
}

But after closing it and opening it several times the gui got somewhat stuck.
Now I'm just drawing the window offscreen which "works" but I would assume doing this would waste memory and CPU resources.

Is there a correct way to handle this?

Demo Makefile Won't Build Demo

The demo Makefile tries to use "MakefileDebug" which doesn't exist. There is a "Makefile" for each platform rather than a "MakefileDebug" file.

Clicking items on unfocused windows

Clicking an item on a window that is out of focus doesn't produce any result.
While that might be ok, there is no hint that the window is indeed out of focus so it feels a bit odd.

I see two ways to solve this:

  • make the items react when click even if the window is not the active window
  • make the header a different color for the active window

"Vector" scalability of the whole UI

Is there any simple way to scale the whole UI in a "vector" way (i.e. not scaling the resulting bitmap, but every single part of the UI separately in a consistent way)? I found just several scaling options, but only for some containers (e.g. panel).

Without scaling, the whole UI is currently not suitable for many deployments (high-res displays of wildly varying sizes - e.g. 5" mobile devices having higher resolution than my 15.4" notebook display).

Also, the sizes differ in the pixel shapes etc., so a separate scaling factor for x and y would be much better than just one common scaling factor.

Example / Demo doesn't build on windows

Just cloned the latest revision and I'm getting these on the GLFW/SDL files:

clang -std=c99 -pedantic -O2 -o bin/node_editor node_editor.c -lglfw3 -lopengl32 -lm -lGLU32 -lGLEW32
In file included from node_editor.c:36:
./../nuklear.h:11384:5: error: use of undeclared identifier 'pad'
    pad.x = style->padding.x + style->border;
    ^
./../nuklear.h:11385:5: error: use of undeclared identifier 'pad'
    pad.y = style->padding.y + style->border;
    ^
2 errors generated.
Makefile:16: recipe for target 'node_editor' failed
make: *** [node_editor] Error 1

centered text widgets with negative x

If you move a button (or any other widget with centered text) out of the left side of the screen, x will get negative and the "center" calculation will give wrong results.

    zr_widget_text, line ~3808

    label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x)/2));
    if (label.x >= label.w/2) label.x -= (label.w/2);

replacing those two lines with:

    label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);

might (maybe) solve the problem?

Development state issues

Yesterday i wrote a few lines of code to test your library, I've updated the code, and well It no longer compiles.GUI_PANEL_CLOSEABLE GUI_PANEL_MINIMIZABLE were gone. gui_panel_begin had different arguments.

Is the library in a rapid development stage, or I am doing something wrong?

Space error

Hey! There is an issue with Spaces on the Windows demo code. It looks like it adds two spaces whenever I hit the space bar once.

Window closing

I'll start creating new issues for you :)

Anyways I'd like to also get the functionality to remove/add the minimize button on windows as well as program in exactly what happens when these buttons are clicked. Also I noticed that occasionally clicking on the status bar at the top of the window will close the window (even though I'm pretty sure I'm not clicking on the X).

Thanks!

Sending user data to draw loops

Imagine you want to control certain aspects of the backend renderer from inside the UI. Right now it is rather difficult to get any kind user data down to the draw loop.

Would it be possible to append a zr_handle user_data to struct zr_context, struct zr_draw_command and struct zr_command. The handling could be similar to zr_set_font.

With zr_set_user_data(struct zr_context*,zr_handle user_data); one would set the user data in the context and this data would get passed down to zr_foreach or zr_draw_foreach through struct zr_command and struct zr_draw_command.

Until zr_set_user_data is called again, always the same user data should end up in the draw loops.

Copy/paste functionality

Hey! So do you think you'll have copy and paste functionality built into this soon?

Thank you so much for all the time you are putting into this by the way!

zr_layout_row issues

Hey! So I was using "zr_layout_row_space_begin" and "...end" today and I noticed that the scroll bar that is added is incorrect. I want to add like a sub-section in the window where the scroll bar is in the middle of the window. I'm trying to add lots of data to the window but I don't want the entire window to scroll down I just want a certain portion of it it (hopefully that makes sense).

As usual thanks for the support!

Making zahnrad touch screen friendly.

I am right now toying around building an interface for iOS and Android and potentially other touch screen devices. Getting a rough port up running on iOS was pretty easy, thanks to the clean structure of zahnrad. I have discovered only one major show stopper and this is the mouse pointer centric approach. On a touch screen there is no concept of hovering for example. And most widgets (those that do not involve dragging) do fire on touch up and not down.

As a workaround I am sending a motion event right before a touch down.

zr_clear(&gui.ctx);

zr_input_begin(&gui.ctx);
zr_input_motion(&gui.ctx, location.x, location.y);
zr_input_end(&gui.ctx);

zr_input_begin(&gui.ctx);
zr_input_button(&gui.ctx, b, location.x, location.y, zr_true);
zr_input_end(&gui.ctx);

run_demo(&gui);

and again a motion event right after a touch up

zr_clear(&gui.ctx);

zr_input_begin(&gui.ctx);
zr_input_button(&gui.ctx, b, location.x, location.y, zr_false);
zr_input_end(&gui.ctx);

zr_input_begin(&gui.ctx);
zr_input_motion(&gui.ctx, 0, 0);
zr_input_end(&gui.ctx);

run_demo(&gui);

This does work surprisingly well, but of course feels quite hackish and does not solve the touch up vs. down issue.

Another issue is the hit test. On a touch screen it is rather difficult to hit small widgets and the solution usually is to extend the hit area virtually to at least 40 x 40 pixel.

I see a huge potential for zahnrad on touch devices.

What do you think?

Cheers, richi

Idea: use higher optimization level in Makefiles for demos

Currently the first use of demos might discourage new users, because they will notice CPU rendering is utterly slow on low-power machines (e.g. Raspberry Pi series). I'm proposing using -O2 by default (because gcc uses -O0 by default).

Minor: spelling mistakes in API

Please don't consider this as nitpicking. I would just like Zahnrad to be the best imgui written in C with stable API.

Except for few spelling mistakes in the documentation (which is not a big deal - I want to issue a pull request during the next 7 days and as I'm not a native speaker, I'll definitely unintentionally skip some typos), I'm more concerned about ones in the API - e.g. functions containing glyphes should rather contain glyphs (some internal structures and variables contain this typo as well). In addition, today I found modifyable -> modifiable.

Add demo mainloops to the normal code base

Hello,

zahnrad looks really interesting.

But to use it, it seems like one needs to copy paste most of the demo code, before a GUI can be drawn. I know, that this is by design - but what's the benefit?

How about adding all the mainloops from the demo as normal code base? (in separate files, so the user can choose which ones are needed)?

For me, the most obvious way would be something like this:

zr_mainloop_x11(my_zahnrad_gui_function);
zr_mainloop_sdl2(my_zahnrad_gui_function);
zr_mainloop_wayland(my_zahnrad_gui_function);
...

... instead of:

run_demo(&gui);

Thanks for making this project!

Minor: use "chart" instead of "graph"

It seems chart would be more suitable instead of graph for API (zr_graph_type, ZR_GRAPH_LINES, ZR_GRAPH_COLUMN, ZR_GRAPH_MAX, zr_graph_event, ZR_GRAPH_HOVERING, ZR_GRAPH_CLICKED, etc.) as the API has nothing to do neither with mathematical graphs nor with graph data structures. Even though nowadays these terms are used sometimes interchangeably, graph is ambiguous and it's usage in a UI library is misleading (not even mentioning the scenario when using Zahnrad for graph visualization).

Just for reference:

https://en.wikipedia.org/wiki/Graph
https://en.wikipedia.org/wiki/Chart
https://en.wikipedia.org/wiki/Wikipedia:Graphs_and_charts

Adding zr_canvas_clear() to zr_convert()

Would it be possible to add a zr_canvas_clear()to the very beginning of zr_convert()?
This would give the ability to run zr_draw_foreach()as a kind of 3rd level cache without always running the ui code first. Another option would be to simply make zr_canvas_clear() public.

Compile issues

I receive the following error when compiling when I set ZR_COMPILE_WITH_VERTEX_BUFFER and
ZR_COMPILE_WITH_FONT to zero:

"/opt/lib/GUI/zahnrad.c: In function ‘zr_uint zr_color32(zr_color)’:
/opt/lib/GUI/zahnrad.c:363:20: error: ‘zr_draw_vertex_color’ was not declared in this scope
/opt/lib/GUI/zahnrad.c:363:41: error: expected ‘,’ or ‘;’ before ‘in’
/opt/lib/GUI/zahnrad.c:364:35: error: expected ‘)’ before ‘in’
/opt/lib/GUI/zahnrad.c:365:35: error: expected ‘)’ before ‘in’
/opt/lib/GUI/zahnrad.c:366:35: error: expected ‘)’ before ‘in’"

Keyboard Navigation / Gamepad

Hey
First of all, thanks a lot for this toolkit, it's great, I've been looking for a cross platform gui toolkit for a while and this fits the bill correctly and this one does.

I'm implementing zahnrad in RetroArch as a new menu driver (retroarch is a sort of multi system emulator and we have several menu drivers but we don't have a traditional mouse + kb driver).

Now I made a basic implementation on our menu driver and I'm wondering, is it possible to navigate the controls with keyboard only or a gamepad? maybe assign an ID to each control and have a selected property that highlights the selected widget? reacting to the click keyevent should be doable already but I'm not sure about the navigation.

win32 demo compilation problems

I ran the "make.bat" file (in the win32 demo section) using the "Developer Command Prompt for VS2015" using administrator privileges, but encountered two errors in the win32.c

win32.c(404): error C2065: 'zr_float': undeclared identifier
win32.c(404): error C2146: syntax error: missing ';' before identifier 'xw'

It fails to create the executable in the bin folder

[Visual studio 2015, Windows 10]

Changing fonts

Hey! I was looking through the OpenGL example and its not entirely clear to me how exactly I change fonts during runtime. Could you show me how to do this?

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.