Open irtusb opened 8 years ago
Please @vurtun review this if you have time
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.
Thanks for writing this up! It's been a good time saver for me.
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)
@jpcima do you mean nk_space_begin
, nk_space_push
and nk_space_end
?
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.
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.
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.
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 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.
@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"?
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.
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:
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.
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.
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..
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.
This text should be in the Wiki.....
This text should be in the Wiki.....
it was written before anything else than the readme and examples existed
did someone implement this using OpenCV?
Prerequisite
.c
or.cpp
) and make sure to#define NK_IMPLEMENTATION
before#include nuklear.h
.demo/
) or write your own. The backend in general is made out of OS window and input management and drawing routines.Context
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 definingNK_INCLUDE_DEFAULT_ALLOCATOR
before#include "nuklear.h"
and just callnk_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
struct nk_user_font
with height (float) and a text length callback. You will have all this info (and more) available when drawingstruct nk_font_atlas atlas;
. if using NK_INCLUDE_DEFAULT_ALLOCATOR thennk_font_atlas_init_default
else one ofnk_font_atlas_init
,nk_font_atlas_init_custom
nk_font_atlas_begin
nk_font_atlas_add_default
,nk_font_atlas_add_from_memory
,nk_font_atlas_add_from_file
.struct nk_font_config
parameter can be null. The returned value from these functions (font) is used later_default
requires NK_INCLUDE_DEFAULT_FONT_from_file
requires NK_INCLUDE_STANDARD_IOvoid* image = nk_font_atlas_bake
glTexImage2D(GL_TEXTURE_2D, ...)
that converts bitmap to texture (for performance if your renderer supports it)nk_font_atlas_end(&atlas, nk_handle_id(texture), &null)
, this will bind texture for every font in atlasnk_style_set_font(&ctx, font)
Main Loop
Event handling
note: don't forget to handle a way to break loop and close window
nk_input_begin
resets leftover state from last framenk_input_motion
,nk_input_key
,nk_input_button
among others. Refer to file_browser.c for a polling example and demos for event loopsnk_input_end
applies changes to grabbing behaviour but may do some other cleaning in the futureGUI
this is where you apply all that immediate mode stuff, a whole topic on its own, but basically you need to
struct nk_panel layout
and pass it tonk_begin
.struct nk_panel
can be understood as a container for temporary state that lives on the stack while the window is build up.nk_begin
creates an empty window and reuses some frame independent state (size, position, flags, ...). It returns true only when the window is actually visible (i.e. panel is not minizized, closed or hidden) otherwise it returns false and you shouldn't add any widgets to the window (guard byif
condition).nk_begin
you can start calling one of the layout functionnk_layout_row_xxx
to setup space for widgetsnk_window_get_canvas(ctx)
and use it as the first argument to nuklear primitives likenk_fill_rect
andnk_stroke_line
nk_begin_titled
and setid
to a custom identifier string. Currently nuklear uses a only id to determine a canvas identity[*]nk_end
finalizes current canvas and allows application to start another onerendering
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
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
. Doing it enables thenk_convert
function that translates this command list into a hardware accesible format. Personally I haven't dealt enough with it to provide further explanationsenum nk_command_type
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'tApplication 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