From 30334ce5e8238e09ef62de0b45d92d896683a963 Mon Sep 17 00:00:00 2001 From: David Maas Date: Sat, 17 Feb 2024 10:38:30 -0600 Subject: [PATCH] Created very quick and dirty implementation of `ImGuiWindowFlags_InheritIdStack`. --- examples/example_win32_directx11/main.cpp | 36 +++++++++++++++++++++++ imgui.cpp | 32 ++++++++++++-------- imgui.h | 1 + imgui_internal.h | 4 +-- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 19422c152a56..3f788377de1d 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -113,7 +113,42 @@ int main(int, char**) ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); + printf("=====================================\n"); + if (ImGui::Button("Show outer test modal")) + ImGui::OpenPopup("TestModal"); + + if (ImGui::BeginPopupModal("TestModal")) + { + ImGui::Text("This is the outer test modal"); + + //ImGui::PushID("InnerModalIdScope"); + if (ImGui::Button("Show inner test modal")) + ImGui::OpenPopup("TestModal"); + + if (ImGui::BeginPopupModal("TestModal")) + { + ImGui::Text("This is the inner test modal"); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + //ImGui::PopID(); + + ImGui::EndPopup(); + } + + if (ImGui::BeginPopupModal("TestModal")) + { + ImGui::Text("Concat"); + ImGui::EndPopup(); + } + + ImGui::ShowMetricsWindow(); + ImGui::ShowDemoWindow(); + ImGui::ShowIDStackToolWindow(); + +#if 0 // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). if (show_demo_window) ImGui::ShowDemoWindow(&show_demo_window); @@ -150,6 +185,7 @@ int main(int, char**) show_another_window = false; ImGui::End(); } +#endif // Rendering ImGui::Render(); diff --git a/imgui.cpp b/imgui.cpp index 05f578316f12..6873e963dbc9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1063,7 +1063,7 @@ static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10); // Multi static void SetCurrentWindow(ImGuiWindow* window); static void FindHoveredWindow(); -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags); +static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags, ImGuiID id); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); @@ -3739,13 +3739,13 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) //----------------------------------------------------------------------------- // ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods -ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NULL) +ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name, ImGuiID id) : DrawListInst(NULL) { memset(this, 0, sizeof(*this)); Ctx = ctx; Name = ImStrdup(name); NameBufLen = (int)strlen(name) + 1; - ID = ImHashStr(name); + ID = id;//ImHashStr(name); IDStack.push_back(ID); MoveId = GetID("#MOVE"); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); @@ -5144,9 +5144,13 @@ void ImGui::Render() windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL); for (ImGuiWindow* window : g.Windows) { + printf("Drawing %p '%s'...\n", window, window->Name); IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) AddRootWindowToDrawData(window); + else + printf(" SUPPRESSED active: %d, !hidden: %d, !childWindow: %d, !renderTopMost0: %d, !renderTopMost1: %d\n", + window->Active, !window->Hidden, (window->Flags & ImGuiWindowFlags_ChildWindow) == 0, window != windows_to_render_top_most[0], window != windows_to_render_top_most[1]); } for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window @@ -5650,12 +5654,12 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s } } -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) +static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags, ImGuiID id) { // Create window the first time //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags); ImGuiContext& g = *GImGui; - ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); + ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name, id); window->Flags = flags; g.WindowsById.SetVoidPtr(window->ID, window); @@ -6377,10 +6381,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet // Find or create - ImGuiWindow* window = FindWindowByName(name); + ImGuiID id = (flags & ImGuiWindowFlags_InheritIdStack) == 0 ? ImHashStr(name) : g.CurrentWindow->GetID(name); + ImGuiWindow* window = FindWindowByID(id); const bool window_just_created = (window == NULL); if (window_just_created) - window = CreateNewWindow(name, flags); + window = CreateNewWindow(name, flags, id); + + printf("Begin window %p '%s'\n", window, name); // [DEBUG] Debug break requested by user if (g.DebugBreakInWindow == window->ID) @@ -10987,7 +10994,8 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); } - flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse; + flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_InheritIdStack; + printf("BeginPopup %x '%s'\n", id, name); const bool is_open = Begin(name, p_open, flags); if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) { @@ -13599,7 +13607,7 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) return g.SettingsIniData.c_str(); } -ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) +ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name, ImGuiID id) { ImGuiContext& g = *GImGui; @@ -13616,7 +13624,7 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1; ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size); IM_PLACEMENT_NEW(settings) ImGuiWindowSettings(); - settings->ID = ImHashStr(name, name_len); + settings->ID = id;//ImHashStr(name, name_len); memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator return settings; @@ -13671,7 +13679,7 @@ static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler* if (settings) *settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry else - settings = ImGui::CreateNewWindowSettings(name); + settings = ImGui::CreateNewWindowSettings(name, ImHashStr(name)); //TODO: This is not the right thing to do as the ID won't match if ImGuiWindowFlags_InheritIdStack was used settings->ID = id; settings->WantApply = true; return (void*)settings; @@ -13714,7 +13722,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window); if (!settings) { - settings = ImGui::CreateNewWindowSettings(window->Name); + settings = ImGui::CreateNewWindowSettings(window->Name, window->ID); window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); } IM_ASSERT(settings->ID == window->ID); diff --git a/imgui.h b/imgui.h index 1346ecacdcc9..cbf56838b389 100644 --- a/imgui.h +++ b/imgui.h @@ -1008,6 +1008,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoNavInputs = 1 << 16, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. + ImGuiWindowFlags_InheritIdStack = 1 << 19, ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, diff --git a/imgui_internal.h b/imgui_internal.h index 3caef13b6039..a8483c79b74b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2597,7 +2597,7 @@ struct IMGUI_API ImGuiWindow bool MemoryCompacted; // Set when window extraneous data have been garbage collected public: - ImGuiWindow(ImGuiContext* context, const char* name); + ImGuiWindow(ImGuiContext* context, const char* name, ImGuiID id); ~ImGuiWindow(); ImGuiID GetID(const char* str, const char* str_end = NULL); @@ -3049,7 +3049,7 @@ namespace ImGui IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); // Settings - Windows - IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); + IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name, ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByID(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByWindow(ImGuiWindow* window); IMGUI_API void ClearWindowSettings(const char* name);