overlay: refactor overlay layering (#739)

## Link to GitHub Issue or related Pull Request, if one exists
n/a

## Description of change

Create three distinct layers for the overlay:

1. Bottommost persistent layer - non-interactable layer that is always
on. This was only for notifications, but now the FPS widget lives here
as well.
2. Overlay windows layer - most interactable windows go here.
3. Topmost main menu - this is reserved for the main menu (escape key)
and this is a modal dialog that occludes the layers below.

Why? 

- `toggle overlay` behavior with FPS widget *also* toggling on/off was a
bit confusing (now they're two separate keys)
- FPS widget is popular, but it caused the entire overlay to be active,
which affects how input is handled
- the main menu being a standalone window was a little awkward (now it's
a modal)

## Testing
This commit is contained in:
bicarus
2026-06-07 17:23:08 -07:00
committed by GitHub
parent bb87aa2944
commit 100caa0f5c
16 changed files with 348 additions and 102 deletions
+11
View File
@@ -146,6 +146,17 @@ namespace overlay::notifications {
float height = 0.f;
if (ImGui::Begin(window_id.c_str(), nullptr, TOAST_FLAGS)) {
// keep toasts above other overlay windows (e.g. the persistent FPS
// window, which may be toggled on after a toast already exists), but
// tuck them behind a blocking modal so they get dimmed/occluded by the
// modal backdrop instead of floating on top of it.
ImGuiWindow *toast_window = ImGui::GetCurrentWindow();
if (ImGuiWindow *modal = ImGui::GetTopMostPopupModal()) {
ImGui::BringWindowToDisplayBehind(toast_window, modal);
} else {
ImGui::BringWindowToDisplayFront(toast_window);
}
const ImVec2 win_pos = ImGui::GetWindowPos();
const ImVec2 win_size = ImGui::GetWindowSize();