vurtun / nuklear

A single-header ANSI C gui library
13.66k stars 1.11k forks source link

How to use this library #226

Open irtusb opened 7 years ago

irtusb commented 7 years ago

Prerequisite

Main interaction point with nuklear is the context: struct nk_context. Depending if you are using one of the demos or wrote your own implementation you either get it automatically fully initialized (in case of you using one of the demos) or you have allocate the object either on stack or on the heap and initialize it yourself.

To initialize the context you have to call one of the nk_init_xxx functions. Each one offers a different set of control over memory but If you don't want to directly manage the memory of nuklear then I would recommend defining NK_INCLUDE_DEFAULT_ALLOCATOR before #include "nuklear.h" and just call nk_init_default.

Important to point out is that you have to pass a font as second parameter. This article describes font handling next so you can just set it to NULL at this point.

Font handling

note: examples author uses only two combinations: low level without vertex buffer and high level with vertex buffer

note: don't forget to handle a way to break loop and close window

this is where you apply all that immediate mode stuff, a whole topic on its own, but basically you need to

Every widget in nuklear is converted internally to a series of primitive drawing commands bound to a specific nuklear context. Again more options. You can choose wheter to react to each of this commands individually or or to draw them in batch mode with a vertex buffer

After event handling, gui drawing and rendering is done you must call nk_clear(&ctx) to reset command list and a new frame can be started. You will get failed assert about two windows with same name if you don't

Application end

After loop is broken you should as always be nice and politelly release resources, free memory and return 0

PS: if you see any grammar error feel free to comment

irtusb commented 7 years ago

Please @vurtun review this if you have time

vurtun commented 7 years ago

Thanks for the write up, I probably will spend some time on the weekend and do a review and add some bits and pieces and further correct some information.

JesseRMeyer commented 7 years ago

Thanks for writing this up! It's been a good time saver for me.

jpcima commented 7 years ago

I am in trouble understanding how the various layouts work and I would be happy to read any documentation on that. I try to program a GUI where I would like fixed positions for about everything, and I do not find a way to accomplish that. I wish I could just designate a rectangle, put the next widget into it, and repeat. I it possible to do without layouts altogether? (I have no idea where to ask except here sorry)

vurtun commented 7 years ago

@jpcima do you mean nk_space_begin, nk_space_push and nk_space_end?

jpcima commented 7 years ago

I don't understand exactly the functionality of nk_layout_space_begin, in particular the purpose of the arguments height and widget_count. However I found I could accomplish exactly what I want using nk_layout_space_begin(ctx, NK_STATIC, 0, INT_MAX). I think I prefer the same way of positioning the JUCE library does, it is simpler code to me and less headache.

vurtun commented 7 years ago

I think I prefer the same way of positioning the JUCE library does, it is simpler code to me and less headache.

If you have an idea or proposal to enhance nuklear go for it. At least tell me what and how they are doing it better so I therefore can make nuklear better. But please don't shit directly into my face, by basically telling me my implementation sucks.

jpcima commented 7 years ago

Ok vurtun, sorry if my previous message sound to you this way. But please believe it is not my intent to throw criticism at your quality of work, please do not take my message wrongly. I would not have interest in contributing if nuklear was bad.

Allow me just to clear some things up. I try to make my first GUI and I am in moderately good progress, with my first 2 widgets made. I get most information through my understanding of source code. Since I have honestly the greatest trouble to understand the layouts, I choose to go with fixed positions, especially because this is what I used in past experience.

I do not suggest to change nuklear. I have little understanding, and no authority to say it should be like this or that. I try to apply a paradigm I am familiar with, and to accomplish that was the objective of my question. The "JUCE way" is only to be understood as fixed + a fancy set of methods to successively subdivide rectangles.

Apparently the documentation currently lacks in nuklear. I have found this page helpful, which is related to Chicken Scheme. If there is a more complete source of information I ignore about, please let me know.

dumblob commented 7 years ago

The "JUCE way" is only to be understood as fixed + a fancy set of methods to successively subdivide rectangles.

I've tried to find any documentation describing positioning and/or layouting in JUCE for about an hour yesterday and completely failed, because I did find literally nothing. @jpcima could you please point me to a documentation or source code describing the "JUCE way" to look at?

By the way, if you're interested in automated screen size independent layouting, go and check the comment on Cassowary in https://github.com/vurtun/nuklear/issues/123#issuecomment-260666623 .

jpcima commented 7 years ago

@jpcima could you please point me to a documentation or source code describing the "JUCE way" to look at?

Yes the JUCE author has a talk where he briefly explains it, which is you can hear at 7:30-12:00. This is what I was refering to. I have figured how to do the similar think in nuklear and it works, so no problem.

By the way, if you're interested in automated screen size independent layouting, go and check the comment on Cassowary in #123 (comment) .

It is not an issue which is on my mind currently but thanks for mentioning.

dumblob commented 7 years ago

@jpcima thanks for the link. This method of "chopping rectangles off from the original big canvas by dividing it horizontally or vertically" seems very easy to use. One could say it produces a binary tree of rectangles in a way as is used e.g. in herbstluftwm for window layouting.

How does one solve (easily) the following things using the "chopping method"? Are there also some "tricks"?

  1. Unlimited overlapping (of widgets, backgrounds, etc.). I can imagine one "resets" the coordinates and size of the current state (which holds basically just the coordinates and size of the remaining rectangle) and draws again. But is it really this easy? Could one use it to draw e.g. menus and submenus (recursively) easily?
  2. Dynamic screen size, resolution, and DPI changes (e.g. rotation of the viewport as basically all smartphones do; or connecting to a different LCD, etc.).
  3. From your experience, the inevitable "layering" (refer to the first question) is how much inconvenient?

I have figured how to do the similar think in nuklear and it works, so no problem.

Please post your results somewhere. Actually this "chopping" method should be trivial to implement with Nuklear.

@vurtun it's worth mentioning in README as this method is API agnostic and serves as a very good start for any GUI (it uses the "immediate mode" principle one after another and nothing beforehand unlike explicit "layouting" or boxing or similar retained UI concepts). We could also try to rewrite some of the examples we have currently to use this method to see how does it scale to larger number of widgets and complexity.

jpcima commented 7 years ago

How does one solve (easily) the following things using the "chopping method"? Are there also some "tricks"?

No particular trick worth noting comes to my mind. I am not sure I am too well placed to answer these questions, because I am a simple user with simple needs, but anyway:

  1. is it really this easy?

My opinion may be naive, but I think so. In composite UIs the overlap is traditionally resolved with z-order attributes, and Imgui makes that z-order explicit in control flow. I do not see a particular problem with this.

  1. Dynamic screen size

If you look back at this talk I linked to, you can observe the positioning is performed in a resize callback, exactly for the purpose to adapt to size changes. It is pretty straight forward. As for anything regarding DPI, I have no idea.

  1. the inevitable "layering" (refer to the first question) is how much inconvenient?

I don't think it is, if you think of something specific please elaborate.

Please post your results somewhere. Actually this "chopping" method should be trivial to implement with Nuklear.

Nothing very extravagant at the time being. This is the UI of a music intrument plugin. Since I have a rough but working GUI atm, I focus temporarily to link the interaction to the program logic. I will later introduce the other music related elements; radial controls, vumeters, plots.. Here is partial C++ source code..

screenshot

carmel4a commented 6 years ago

Ok, as I don't see better place... As I understand:

const struct nk_command *cmd = 0;
nk_foreach(cmd, this->ctx_ptr){
    switch (cmd->type) {
        case NK_COMMAND_NOP:
            break;
        case NK_COMMAND_SCISSOR:
            [HERE]
        case NK_COMMAND_LINE:
            [HERE]
            cmd->sth //doesn't work
        ...

in [HERE] I should put my render backend. Should I be able to get command properties at this point? If no - how that should works? How can I know exacly which line I need to draw, etc.

MrDChristop commented 5 years ago

This text should be in the Wiki.....

irtusb commented 5 years ago

This text should be in the Wiki.....

it was written before anything else than the readme and examples existed

omricarmi commented 4 years ago

did someone implement this using OpenCV?