pthom / imgui_bundle

Dear ImGui Bundle: an extensive set of Ready-to-use widgets and libraries, based on ImGui. Start your first app in 5 lines of code, or less. Whether you prefer Python or C++, this pack has your back!
https://pthom.github.io/imgui_bundle/
MIT License
588 stars 61 forks source link

Responsiveness of immapp/hello_imgui - part of imgui_bundle #225

Open Johndeep opened 1 week ago

Johndeep commented 1 week ago

Hello again, I have a question regarding the power saving and responsiveness of the gui interface. No bugs, just a suggestion or idea. Even optional if you want to.

Anyway, until now, the responsiveness of hello_imgui seems to be based on dynamic fps, which runs between, for example 3 fps to 60 fps. But what about "interface refresh on demand"? What I mean by this is that the interface only refreshes if there is any interaction with it.

I achieved this for example in glfw by using glfw.wait_events() instead of glfw.poll_events(). And every time I interacted with the window or want the interface/application to update the content, I always called glfw.post_empty_event(), which can be called even from different threads.

I know this can also be achieved in SDL2 somehow, I think it was with SDL_WaitEvent.

In any case, this allowed me to practically having a standstill image with practically 0 fps until I hovered with the mouse or had a timer, which regularly called glfw.post_empty_event(), which can be limited to 60 fps again for example. I.e. for animation on demand.

Long story, short question: Are there plans to add something like glfw.post_empty_event() in hello_imgui to refresh the frames on demand?

I had this thought, because during tinkering, every time I clicked on a drop down menu in imgui, it seems to have this 3 fps limitation still, which makes it also lagging, if you're not moving the mouse. (To reproduce this case, create a simple combo box and then hover the mouse there in hello_imgui. Don't move the mouse and simply click on it.) I always solved this lagging by calling glfw.post_empty_event() immediately after clicking.

===

To properly continue the question from #223 about framerate control and disabling vsync, I rather think it is better to keep the 60/120 fps (or whatever Hz your monitor has) for CPUs sake, since no limit means the CPU will run 100% with every move of the mouse. Yes the interface becomes "over-responsive", but by sacrificing power saving.

pthom commented 1 week ago

See https://pthom.github.io/hello_imgui/book/doc_params.html#fps-idling

In any case, this allowed me to practically having a standstill image with practically 0 fps until I hovered with the mouse or had a timer

You can achieve similar result by setting fpsIdle (aka fps_idle) to 0.001 for example

Are there plans to add something like glfw.post_empty_event() in hello_imgui to refresh the frames on demand?

Simply set enableIdling aka enable_iding = False temporarily

pthom commented 2 days ago

Hello, I'm closing this issue because I suppose my answer did solve it.

Please post again here if it did not.

Johndeep commented 2 days ago

Ah, okay, sorry for not answering this here also (and soon enough).

  1. As I've said in the other issue, if I set fpsIdle to a very low value, it takes ages until the hello_imgui window pops up. It seems that the very first Frame is also linked to this refresh value.

  2. And then connected to this, temporarily setting enable_iding = True ONLY works okay-ish, if the next frame comes soon after.

For example, if I activate a combo menu, usually it pops up according to what I've set in fpsIdle or when I move the mouse afterwards. But let's say I want to send an update signal to refresh Info displayed in imgui window from another thread or process, this temporarily setting enable_iding = False does not work as intended.

What currently happens with suggestion from above, let's say, fpsIdle is set to value 0.1 (update every 10 seconds):

===

Can I make use of the very callback event, which triggers similar to the user interface interaction via mouse? I know this is a very specific problem and would have a rather low priority. But I wanted it to have it said still.

pthom commented 7 hours ago

The idling logic is complex, because of the multiple cases that have to be handled. I reviewed it a bit in order to simplify it.

https://github.com/pthom/hello_imgui/blob/master/src/hello_imgui/internal/backend_impls/abstract_runner.cpp#L1027-L1095

Normally it should not be slow at startup anymore, even if the FPS is very low, see:

https://github.com/pthom/hello_imgui/blob/7bec671185d540eb8d59327eb682bbbab06bc251/src/hello_imgui/internal/backend_impls/abstract_runner.cpp#L1050C1-L1051C51

And every time I interacted with the window or want the interface/application to update the content, I always called glfw.post_empty_event(), which can be called even from different threads.

Whenever the app if idling, it is waiting for an event to be caught by the platform backend (i.e. SDL or GLFW) see: https://github.com/pthom/hello_imgui/blob/7bec671185d540eb8d59327eb682bbbab06bc251/src/hello_imgui/internal/backend_impls/abstract_runner.cpp#L1067-L1071 . So, posting an empty event using glfw.post_empty_event() should work, I guess.

pthom commented 7 hours ago

And to answer completely if you want to disable idling an exit of a wait loop you have to do both: