vurtun / nuklear

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

setting window bounds for windows which are not user-modifiable #305

Closed inolen closed 7 years ago

inolen commented 7 years ago

I regularly use nuklear to render fullscreen elements like so:

badwindow

However, due to the way windows are cached, I must call nk_window_set_bounds after each nk_begin to force the bounds for these fullscreen elements or else the bounds remain what they were initially created with, which breaks down as the window itself is resized.

Would it make any sense for windows which are not user-modifiable (e.g. not flagged with without NK_WINDOW_MOVABLE / NK_WINDOW_SCALABLE) to always have their bounds set by nk_begin, or is that an unwanted inconsistency in the API?

vurtun commented 7 years ago

Hey, yeah this is one of my API crimes I committed with nuklear. Basically I should have used either a binding style API or even better a bindless API with IDs to modify a window directly and remove them from my immediate mode API. Since I don't want to rewrite the whole API your solution seems enticing. The problem like you said is inconsistency, the question is to what extend. Is this behavior really inconsistent because basically if the window cannot change by user input it should be able to be modified directly. It is almost something to be expected, but it is just not really user friendly.

Another question is if nuklear should be kept consistent and I would only provide a hack which to include if you need it or if it should be directly included into nuklear. But since this an actual bug that can cause problems I think it is worth it to make these changes directly. If you want then you can create a PR or if you don't have the time then I will make these changes. The changes are not really complex just add an if inside nk_begin_titled to set the window position,size if window is not scalable and movable.

dumblob commented 7 years ago

Basically I should have used either a binding style API or even better a bindless API with IDs to modify a window directly and remove them from my immediate mode API.

Well, I was thinking about a "bindless"-like API variant some time ago and decided to give it a try for our needs. @vurtun, do you have something particular in mind we should follow or take into account? So far we're designing the "new" API, but because issues related to windowing are a bit repetitive requests, I'd like to rather first discuss the new API with you for the case you would like to incorporate such a redesigned API to Nuklear upstream instead of "forking" Nuklear. We're prepared to totally redesign Nuklear API if needed.

inolen commented 7 years ago

@vurtun if you have the bandwidth to make the changes, that'd be great, otherwise I'll submit a pr in a week or two.

Edit: Stopped being lazy and opened a pr.

vurtun commented 7 years ago

@inolen thanks for the PR. @dumblob Basically what I thought about is that it makes no sense for windows to be part of the immediate mode API since they are persistent objects which the users needs control over especially live time. Basically a simple binding API would look like this:

void nk_window_generate(struct nk_context*, int count, int *window_ids);
void nk_window_delete(struct nk_context*, int count, int *window_ids);
void nk_window_enable(struct nk_context*, int window_id, nk_flags flags);
void nk_window_disable(struct nk_context*, int window_id, nk_flags flags);
void nk_window_set_bounds(struct nk_context*, int window_id, struct nk_rect);
void nk_begin(struct nk_context*, int window_id);
void nk_end(struct nk_context*);

The binding API is not that different from the current API and wouldn't even require that much code changes but it would invalidate a lot of code already written.

A bindless API is a lot more difficult to pull off, and a lot of changes would go deep. Windows basically would need total memory control for themself so that they could be freely binded and unbinded while still keeping their state persistent until the frame was finished. It is not impossible but definitely a little bit more complex.

Of course at that point you could almost just use this current version with multiple nk_context and one window per `nk_context' and do window layouting yourself (which is not really that hard to pull of). Small note depending on what you do this actually would even make sense.

dumblob commented 7 years ago

@vurtun thanks for the pointers.

Basically what I thought about is that it makes no sense for windows to be part of the immediate mode API since they are persistent objects which the users needs control over especially live time.

My words.

By the way, could you please describe these deepest ideas about possible future Nuklear direction in a (long term) TODO/FUTURE_IDEAS section of README?

Windows basically would need total memory control for themself so that they could be freely binded and unbinded while still keeping their state persistent until the frame was finished.

This is important to realize, thanks!

Btw same as above - fits a TODO section.

you could almost just use this current version with multiple nk_context and one window per `nk_context' and do window layouting yourself

Well, this is what we're currently up to. There is some boiler plate code, but it seems to more or less work.

vurtun commented 7 years ago

By the way, could you please describe these deepest ideas about possible future Nuklear direction in a (long term) TODO/FUTURE_IDEAS section of README?

Honestly there are no long term ideas/todos at the moment. I personally stepped away from pure immediate mode UIs. They don't make a lot of sense for me anymore if used for everything. Basically if you think about it 85-95% of your UI is fixed and by that I don't mean by size or position but purely existential.

More specific immediate mode UIs are extremely simple and easy to use for UI components representing data structures like list, trees or graphs. In retain mode UIs you would have to duplicate your own tree or list into a UI data structure which forces you to manage your as well as a separate UI data structure. It is also the reason why it is such a pain to work with these libraries. Immediate mode solves this problem by basically just pushing the data into the UI library which will draw and update it. There is not data structure management on the UI side only on your side, that what is so nice about it.

But you don't need this amount of dynamic for most of your UI. All of your windows and widgets are basically compile time known except for these data structure UI representations. The realization basically took me quite a long time and both immediate as well as retain mode GUI libraries misunderstand it.

Immediate mode libraries are often to dynamic which results in quite overly complicated code, while libraries like Qt, Wxwidget and basically all Java libraries are in a weird place and do the worst possible thing. They allow you to load the UI from file even though most of the UI is compile time known and do not need to be loadable anyway and the dynamic parts are these weird UI specific data structures.

So basically what I am currently doing at work (reason why I am not allowed to extend or even rewrite this libraries with my findings) is I have a compile time known UI (basically just big c data tables) for almost everything and an immediate mode UI part for all cases where you normally would use data structures in retain mode.

That is one of the reasons why (the other one is just time) I am not doing a lot outside bug fixes on nuklear anymore. I already spend every day at work doing low level UI and I can't get myself to commit any big changes to nuklear.

dumblob commented 7 years ago

Hi @vurtun, that's a bit surprising but very interesting news. Actually I find it amazing, that you're working on another solution of "the UI issue". The idea of properly combining the retained UI and immediate mode UI is a new one for me. I'm hesitating to ask, but will your employer allow you to publish your work on this new UI library at some point? Or some parts of it? Or at least detailed core ideas used in it allowing community to leverage the research?

Either way, I wish you good luck with working on the new concept!

By the way, it would make sense to make it clear to the huge Nuklear user-base, that you're deliberately not working and will not work on any new features, because you're basically working on a quite different "successor". Mentioning this at the top of Readme.md in bold should do.

vurtun commented 7 years ago

I'm hesitating to ask, but will your employer allow you to publish your work on this new UI library at some point? Or some parts of it? Or at least detailed core ideas used in it allowing community to leverage the research?

There is a possibility but I cannot promise anything at this point, it is still under development even if everything works out as planned and my employer really wants to open source it. Furthermore it probably will be a lot more specific for our use cases and not so much a general library to the extend nuklear is. So no promises for a public release at this point in time. The same basically stand true for publishing a write up of core ideas which I am not really good at (I am not a particular good writer especially in english)

Either way, I wish you good luck with working on the new concept!

Thanks it is both really interesting and I learned a lot and so far the resulting code is a lot simple than nuklear for basically all complicated cases.

By the way, it would make sense to make it clear to the huge Nuklear user-base, that you're deliberately not working and will not work on any new features, because you're basically working on a quite different "successor". Mentioning this at the top of Readme.md in bold should do.

Hm not really sure it is required, it is not like I abandoned nuklear, like I said I am commited to fix all bugs and oddities I just won't do anymore big breaking changes.