Custom made IMGUI: Handling overlapping widgets

I am implementing a IMGUI system in Lua after watching Casey's lecture on the subject. I have got the basic stuff working but now, I want to implement "windows" that will hold widgets and expand/contract depending on widget dimensions. The problem that I have encountered is: if I allow users to change the position of these windows (say, by dragging and dropping), it is possible that a window might overlap another window in a way that the two different widgets occupy the same 2D position on screen. If the lower widget's call comes before upper widget's call, the both widgets will register as active and code associated with both of them will be executed.

I guess this is basically a window focus problem which is generally handled by window managers and not windowing toolkits; however, in a game editor, this behavior (of having multiple windows and being able to drag windows and overlap them) is sometimes useful.

Is there any way to solve this problem with immediate mode paradigm?



Added: One obvious way would be to only do MouseOnWidget tests if their corresponding window is in focus; if not, widgets are only rendered. However, this just shifts the problem from overlapping widgets to overlapping windows (how to know which window to bring into focus by click/hover when many of them are overlapping).

Edited by Naman Dixit on
keep a cached stack of window bounds from the last frame and don't react to clicks if there is a window later that will take the click
ratchetfreak's plan sounds good and won't force you to change to much of your system. But if you want even more flexibility at the cost of having to alter your system a lot you might think about trying to write the GUI API as just generating a list of commands and then having one call at the end of the GUI that can execute everything.

In C++ the only problem with this is that the usual IMGUI API with the if will not work.

1
2
3
if (do_button(button_parameters)){
    do_button_result();
}


It won't work because the command you push onto the list won't be resolved until later, so it is impossible to know whether the button should return true or false. I made it work with a system of ids, so each GUI item gets a unique id, then whichever item is activated has it's id stored in an "activated" field that persists to the next frame and THEN the do_button call can return true.

However since you're working in Lua which has beautiful support for lambdas and closures you could instead have calls like:

1
2
3
do_button(button_parameters, function(params_if_you_want)
    -- do button results
end)


Then instead of waiting until the next frame, you can store the lambda as a part of the command in the command list, and when you resolve which item to activate you then call it's lambda. This gives you the advantage that you know all of the state changes caused by your GUI will come after the GUI has been fully executed this frame, which is a nice guarantee to have.

Edited by Allen Webster on Reason: clarity
C++11 has nice support for lambdas too, so one can do:

1
do_button(params, []{ do_button_result(); });


Use std::function for the callbacks.

Another approach is to reverse the draw order, so the first widget submitted is the last rendered.

I'm not really sure which approach is better. Reversing the draw order allows you to draw things based on the results of other things:

1
2
3
if(do_disclosure_triangle( myID )) {
   // do more widgets
}