From 0cabe4dedfb5a8784ffac3e8f974a63fd0fd8dd3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 19:29:33 +0100 Subject: [PATCH] Viewport: Added ImGuiWindowClass / SetNextWindowClass() (concept imported from Docking ImGuiDockFamily), which currently allows to overwrite viewport flags on a per-window basis. Exposed FindViewportByID(). Win32: Support for ParentViewportId. (#1542) --- examples/imgui_impl_win32.cpp | 5 ++++- imgui.cpp | 20 ++++++++++++++++---- imgui.h | 18 +++++++++++++++++- imgui_internal.h | 4 +++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index b2134b30b..9d290fd05 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -454,8 +454,11 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) viewport->PlatformUserData = data; // Select style and parent window - HWND parent_window = g_hWnd; ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &data->DwStyle, &data->DwExStyle); + HWND parent_window = NULL; + if (viewport->ParentViewportId != 0) + if (ImGuiViewport* parent_viewport = ImGui::FindViewportByID(viewport->ParentViewportId)) + parent_window = (HWND)parent_viewport->PlatformHandle; // Create window RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) }; diff --git a/imgui.cpp b/imgui.cpp index 681d8210b..0902ea3bf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4982,6 +4982,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); } + window->WindowClass = g.NextWindowData.WindowClass; if (g.NextWindowData.CollapsedCond) SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); if (g.NextWindowData.FocusCond) @@ -5180,6 +5181,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) viewport_flags |= ImGuiViewportFlags_NoDecoration; + // We can overwrite viewport flags using ImGuiWindowClass (advanced users) + window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId ? window->WindowClass.ParentViewportId : IMGUI_VIEWPORT_DEFAULT_ID; + if (window->WindowClass.ViewportFlagsOverrideMask) + viewport_flags = (viewport_flags & ~window->WindowClass.ViewportFlagsOverrideMask) | (window->WindowClass.ViewportFlagsOverrideValue & window->WindowClass.ViewportFlagsOverrideMask); + // We also tell the back-end that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha viewport_flags |= ImGuiViewportFlags_NoRendererClear; window->Viewport->Flags = viewport_flags; @@ -6343,6 +6349,12 @@ void ImGui::SetNextWindowViewport(ImGuiID id) g.NextWindowData.ViewportId = id; } +void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.WindowClass = *window_class; +} + // In window space (not screen space!) ImVec2 ImGui::GetContentRegionMax() { @@ -7253,7 +7265,7 @@ ImGuiViewport* ImGui::GetMainViewport() return g.Viewports[0]; } -ImGuiViewportP* ImGui::FindViewportByID(ImGuiID id) +ImGuiViewport* ImGui::FindViewportByID(ImGuiID id) { ImGuiContext& g = *GImGui; for (int n = 0; n < g.Viewports.Size; n++) @@ -7493,7 +7505,7 @@ static void ImGui::UpdateViewportsNewFrame() ImGuiViewportP* viewport_hovered = NULL; if (g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) { - viewport_hovered = g.IO.MouseHoveredViewport ? FindViewportByID(g.IO.MouseHoveredViewport) : NULL; + viewport_hovered = g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(g.IO.MouseHoveredViewport) : NULL; if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs)) { // Back-end failed at honoring its contract if it returned a viewport with the _NoInputs flag. @@ -7646,7 +7658,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) // Attempt to restore saved viewport id (= window that hasn't been activated yet), try to restore the viewport based on saved 'window->ViewportPos' restored from .ini file if (window->Viewport == NULL && window->ViewportId != 0) { - window->Viewport = FindViewportByID(window->ViewportId); + window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId); if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None); } @@ -7655,7 +7667,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) if (g.NextWindowData.ViewportCond) { // Code explicitly request a viewport - window->Viewport = FindViewportByID(g.NextWindowData.ViewportId); + window->Viewport = (ImGuiViewportP*)FindViewportByID(g.NextWindowData.ViewportId); window->ViewportId = g.NextWindowData.ViewportId; // Store ID even if Viewport isn't resolved yet. } else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu)) diff --git a/imgui.h b/imgui.h index 6d7f8dd22..8154df6e0 100644 --- a/imgui.h +++ b/imgui.h @@ -114,6 +114,7 @@ struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbb][,ccccc]") struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) struct ImGuiViewport; // Viewport (generally ~1 per window to output to at the OS level. Need per-platform support to use multiple viewports) +struct ImGuiWindowClass; // Window class (rare/advanced uses: provide hints to the platform back-end via altered viewport flags and parent/child info) // Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. @@ -276,6 +277,7 @@ namespace ImGui IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. IMGUI_API void SetNextWindowViewport(ImGuiID viewport_id); // set next window viewport + IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (rare/advanced uses: provide hints to the platform back-end via altered viewport flags and parent/child info) IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). @@ -688,6 +690,7 @@ namespace ImGui IMGUI_API void UpdatePlatformWindows(); // call in main loop. will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport. IMGUI_API void RenderPlatformWindowsDefault(void* platform_arg = NULL, void* renderer_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport. may be reimplemented by user for custom rendering needs. IMGUI_API void DestroyPlatformWindows(); // call DestroyWindow platform functions for all viewports. call from back-end Shutdown() if you need to close platform windows before imgui shutdown. otherwise will be called by DestroyContext(). + IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id); // this is a helper for back-ends. IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); // this is a helper for back-ends. the type platform_handle is decided by the back-end (e.g. HWND, MyWindow*, GLFWwindow* etc.) } // namespace ImGui @@ -1430,6 +1433,18 @@ struct ImGuiPayload bool IsDelivery() const { return Delivery; } }; +// [BETA] Rarely used / very advanced uses only. Use with SetNextWindowClass() function. +// Provide hints to the platform back-end via altered viewport flags (enable/disable OS decoration, OS task bar icons, etc.) and OS level parent/child relationships. +struct ImGuiWindowClass +{ + ImGuiID ClassId; // User data. 0 = Default class (unclassed) + ImGuiID ParentViewportId; // Hint for the platform back-end. If non-zero, the platform back-end can create a parent<>child relationship between the platform windows. Not conforming back-ends are free to e.g. parent every viewport to the main viewport or not. + ImGuiViewportFlags ViewportFlagsOverrideMask; // Viewport flags to override when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. + ImGuiViewportFlags ViewportFlagsOverrideValue; // Viewport flags values to override when a window of this class owns a viewport. + + ImGuiWindowClass() { ClassId = 0; ParentViewportId = 0; ViewportFlagsOverrideMask = ViewportFlagsOverrideValue = 0x00; } +}; + //----------------------------------------------------------------------------- // Obsolete functions (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) //----------------------------------------------------------------------------- @@ -2235,6 +2250,7 @@ struct ImGuiViewport ImVec2 Size; // Size of viewport in pixel float DpiScale; // 1.0f = 96 DPI = No extra scale ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame(). + ImGuiID ParentViewportId; // (Advanced) 0: no parent. Instruct the platform back-end to setup a parent/child relationship between platform windows. void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.) void* PlatformUserData; // void* to hold custom data structure for the OS / platform (e.g. windowing info, render context) @@ -2243,7 +2259,7 @@ struct ImGuiViewport bool PlatformRequestMove; // Platform window requested move (e.g. window was moved by the OS / host window manager, authoritative position will be OS window position) bool PlatformRequestResize; // Platform window requested resize (e.g. window was resized by the OS / host window manager, authoritative size will be OS window size) - ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; RendererUserData = PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; } + ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; ParentViewportId = 0; RendererUserData = PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; } ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } }; diff --git a/imgui_internal.h b/imgui_internal.h index fee712b9a..16f5dae16 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -714,6 +714,7 @@ struct ImGuiNextWindowData void* SizeCallbackUserData; float BgAlphaVal; ImGuiID ViewportId; + ImGuiWindowClass WindowClass; ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it. ImGuiNextWindowData() @@ -733,6 +734,7 @@ struct ImGuiNextWindowData void Clear() { PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = ViewportCond = 0; + WindowClass = ImGuiWindowClass(); } }; @@ -1121,6 +1123,7 @@ struct IMGUI_API ImGuiWindow char* Name; ImGuiID ID; // == ImHash(Name) ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_ + ImGuiWindowClass WindowClass; // Advanced users only. Set with SetNextWindowClass() ImGuiViewportP* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here ImGuiID ViewportId; // We backup the viewport id (since the viewport may disappear or never be created if the window is inactive) ImVec2 ViewportPos; // We backup the viewport position (since the viewport may disappear or never be created if the window is inactive) @@ -1331,7 +1334,6 @@ namespace ImGui IMGUI_API void UpdateMouseMovingWindow(); // Viewports - IMGUI_API ImGuiViewportP* FindViewportByID(ImGuiID id); IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport); IMGUI_API void ShowViewportThumbnails();