Viewports: Lots of comments about setting up multi-viewports. (#1542)

This commit is contained in:
ocornut 2020-03-05 18:26:18 +01:00
parent 7e00cde8a9
commit 1b579a110d

186
imgui.h
View File

@ -32,7 +32,7 @@ Index of this file:
// Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
// Draw List API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
// Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// Platform interface for multi-viewport support (ImGuiPlatformMonitor, ImGuiPlatformIO, ImGuiViewport)
// Platform interface for multi-viewport support (ImGuiPlatformIO, ImGuiPlatformMonitor, ImGuiViewportFlags, ImGuiViewport)
*/
@ -775,11 +775,12 @@ namespace ImGui
IMGUI_API void MemFree(void* ptr);
// (Optional) Platform/OS interface for multi-viewport support
// Read comments around the ImGuiPlatformIO structure for more details.
// Note: You may use GetWindowViewport() to get the current viewport of the current window.
IMGUI_API ImGuiPlatformIO& GetPlatformIO(); // platform/renderer functions, for back-end to setup + viewports list.
IMGUI_API ImGuiViewport* GetMainViewport(); // main viewport. same as GetPlatformIO().MainViewport == GetPlatformIO().Viewports[0].
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 which doesn't have the ImGuiViewportFlags_Minimized flag set. May be reimplemented by user for custom rendering needs.
IMGUI_API void RenderPlatformWindowsDefault(void* platform_render_arg = NULL, void* renderer_render_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport which doesn't have the ImGuiViewportFlags_Minimized flag set. 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.)
@ -2392,11 +2393,116 @@ struct ImFont
//-----------------------------------------------------------------------------
// [BETA] Platform interface for multi-viewport support
// - completely optional, for advanced users!
// - this is used for back-ends aiming to support the seamless creation of multiple viewport (= multiple Platform/OS windows)
// dear imgui manages the viewports, and the back-end create one Platform/OS windows for each secondary viewport.
// - if you are new to dear imgui and trying to integrate it into your engine, you should probably ignore this for now.
//-----------------------------------------------------------------------------
// (Optional) This is completely optional, for advanced users!
// If you are new to Dear ImGui and trying to integrate it into your engine, you can probably ignore this for now.
//
// This feature allows you to seamlessly drag Dear ImGui windows outside of your application viewport.
// This is achieved by creating new Platform/OS windows on the fly, and rendering into them.
// Dear ImGui manages the viewport structures, and the back-end create and maintain one Platform/OS window for each of those viewports.
//
// See Glossary https://github.com/ocornut/imgui/wiki/Glossary for details about some of the terminology.
// See Thread https://github.com/ocornut/imgui/issues/1542 for gifs, news and questions about this evolving feature.
//
// About the coordinates system:
// - When multi-viewports are enabled, all Dear ImGui coordinates become absolute coordinates (same as OS coordinates!)
// - So e.g. ImGui::SetNextWindowPos(ImVec2(0,0)) will position a window relative to your primary monitor!
// - If you want to position windows relative to your main application viewport, use ImGui::GetMainViewport()->Pos as a base position.
//
// Steps to use multi-viewports in your application, when using a default back-end from the examples/ folder:
// - Application: Enable feature with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// - Back-end: The back-end initialization will setup all necessary ImGuiPlatformIO's functions and update monitors info every frame.
// - Application: In your main loop, call ImGui::UpdatePlatformWindows(), ImGui::RenderPlatformWindowsDefault() after EndFrame() or Render().
// - Application: Fix absolute coordinates used in ImGui::SetWindowPos() or ImGui::SetNextWindowPos() calls.
//
// Steps to use multi-viewports in your application, when using a custom back-end:
// - Important: THIS IS NOT EASY TO DO and comes with many subtleties not described here!
// It's also an experimental feature, so some of the requirements may evolve.
// Consider using default back-ends if you can. Either way, carefully follow and refer to examples/ back-ends for details.
// - Application: Enable feature with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// - Back-end: Hook ImGuiPlatformIO's Platform_* and Renderer_* callbacks (see below).
// Set 'io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports' and 'io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports'.
// Update ImGuiPlatformIO's Monitors list every frame.
// Update MousePos every frame, in absolute coordinates.
// - Application: In your main loop, call ImGui::UpdatePlatformWindows(), ImGui::RenderPlatformWindowsDefault() after EndFrame() or Render().
// You may skip calling RenderPlatformWindowsDefault() if its API is not convenient for your needs. Read comments below.
// - Application: Fix absolute coordinates used in ImGui::SetWindowPos() or ImGui::SetNextWindowPos() calls.
//
// About ImGui::RenderPlatformWindowsDefault():
// - This function is a mostly a _helper_ for the common-most cases, and to facilitate using default back-ends.
// - You can check its simple source code to understand what it does.
// It basically iterates secondary viewports and call 4 functions that are setup in ImGuiPlatformIO, if available:
// Platform_RenderWindow(), Renderer_RenderWindow(), Platform_SwapBuffers(), Renderer_SwapBuffers()
// Those functions pointers exists only for the benefit of RenderPlatformWindowsDefault().
// - If you have very specific rendering needs (e.g. flipping multiple swap-chain simultaneously, unusual sync/threading issues, etc.),
// you may be tempted to ignore RenderPlatformWindowsDefault() and write customized code to perform your renderingg.
// You may decide to setup the platform_io's *RenderWindow and *SwapBuffers pointers and call your functions through those pointers,
// or you may decide to never setup those pointers and call your code directly. They are a convenience, not an obligatory interface.
//-----------------------------------------------------------------------------
// (Optional) Access via ImGui::GetPlatformIO()
struct ImGuiPlatformIO
{
//------------------------------------------------------------------
// Input - Back-end interface/functions + Monitor List
//------------------------------------------------------------------
// (Optional) Platform functions (e.g. Win32, GLFW, SDL2)
// For reference, the second column shows which function are generally calling the Platform Functions:
// N = ImGui::NewFrame() ~ beginning of the dear imgui frame: read info from platform/OS windows (latest size/position)
// F = ImGui::Begin(), ImGui::EndFrame() ~ during the dear imgui frame
// U = ImGui::UpdatePlatformWindows() ~ after the dear imgui frame: create and update all platform/OS windows
// R = ImGui::RenderPlatformWindowsDefault() ~ render
// D = ImGui::DestroyPlatformWindows() ~ shutdown
// The general idea is that NewFrame() we will read the current Platform/OS state, and UpdatePlatformWindows() will write to it.
//
// The functions are designed so we can mix and match 2 imgui_impl_xxxx files, one for the Platform (~window/input handling), one for Renderer.
// Custom engine back-ends will often provide both Platform and Renderer interfaces and so may not need to use all functions.
// Platform functions are typically called before their Renderer counterpart, apart from Destroy which are called the other way.
// Platform function --------------------------------------------------- Called by -----
void (*Platform_CreateWindow)(ImGuiViewport* vp); // . . U . . // Create a new platform window for the given viewport
void (*Platform_DestroyWindow)(ImGuiViewport* vp); // N . U . D //
void (*Platform_ShowWindow)(ImGuiViewport* vp); // . . U . . // Newly created windows are initially hidden so SetWindowPos/Size/Title can be called on them before showing the window
void (*Platform_SetWindowPos)(ImGuiViewport* vp, ImVec2 pos); // . . U . . // Set platform window position (given the upper-left corner of client area)
ImVec2 (*Platform_GetWindowPos)(ImGuiViewport* vp); // N . . . . //
void (*Platform_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // . . U . . // Set platform window client area size (ignoring OS decorations such as OS title bar etc.)
ImVec2 (*Platform_GetWindowSize)(ImGuiViewport* vp); // N . . . . // Get platform window client area size
void (*Platform_SetWindowFocus)(ImGuiViewport* vp); // N . . . . // Move window to front and set input focus
bool (*Platform_GetWindowFocus)(ImGuiViewport* vp); // . . U . . //
bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp); // N . . . . // Get platform window minimized state. When minimized, we generally won't attempt to get/set size and contents will be culled more easily
void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* str); // . . U . . // Set platform window title (given an UTF-8 string)
void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // . . U . . // (Optional) Setup window transparency
void (*Platform_UpdateWindow)(ImGuiViewport* vp); // . . U . . // (Optional) Called by UpdatePlatformWindows(). Optional hook to allow the platform back-end from doing general book-keeping every frame.
void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Main rendering (platform side! This is often unused, or just setting a "current" context for OpenGL bindings). 'render_arg' is the value passed to RenderPlatformWindowsDefault().
void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Call Present/SwapBuffers (platform side! This is often unused!). 'render_arg' is the value passed to RenderPlatformWindowsDefault().
float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // N . . . . // (Optional) [BETA] FIXME-DPI: DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI.
void (*Platform_OnChangedViewport)(ImGuiViewport* vp); // . F . . . // (Optional) [BETA] FIXME-DPI: DPI handling: Called during Begin() every time the viewport we are outputting into changes, so back-end has a chance to swap fonts to adjust style.
void (*Platform_SetImeInputPos)(ImGuiViewport* vp, ImVec2 pos); // . F . . . // (Optional) Set IME (Input Method Editor, e.g. for Asian languages) input position, so text preview appears over the imgui input box. FIXME: The call timing of this is inconsistent because we want to support without multi-viewports.
int (*Platform_CreateVkSurface)(ImGuiViewport* vp, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); // (Optional) For a Vulkan Renderer to call into Platform code (since the surface creation needs to tie them both).
// (Optional) Renderer functions (e.g. DirectX, OpenGL, Vulkan)
void (*Renderer_CreateWindow)(ImGuiViewport* vp); // . . U . . // Create swap chain, frame buffers etc. (called after Platform_CreateWindow)
void (*Renderer_DestroyWindow)(ImGuiViewport* vp); // N . U . D // Destroy swap chain, frame buffers etc. (called before Platform_DestroyWindow)
void (*Renderer_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // . . U . . // Resize swap chain, frame buffers etc. (called after Platform_SetWindowSize)
void (*Renderer_RenderWindow)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Clear framebuffer, setup render target, then render the viewport->DrawData. 'render_arg' is the value passed to RenderPlatformWindowsDefault().
void (*Renderer_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Call Present/SwapBuffers. 'render_arg' is the value passed to RenderPlatformWindowsDefault().
// (Optional) Monitor list
// - Updated by: app/back-end. Update every frame to dynamically support changing monitor or DPI configuration.
// - Used by: dear imgui to query DPI info, clamp popups/tooltips within same monitor and not have them straddle monitors.
ImVector<ImGuiPlatformMonitor> Monitors;
//------------------------------------------------------------------
// Output - List of viewports to render into platform windows
//------------------------------------------------------------------
// Viewports list (the list is updated by calling ImGui::EndFrame or ImGui::Render)
// (in the future we will attempt to organize this feature to remove the need for a "main viewport")
ImGuiViewport* MainViewport; // Guaranteed to be == Viewports[0]
ImVector<ImGuiViewport*> Viewports; // Main viewports, followed by all secondary viewports.
ImGuiPlatformIO() { memset(this, 0, sizeof(*this)); } // Zero clear
};
// (Optional) This is required when enabling multi-viewport. Represent the bounds of each connected monitor/display and their DPI.
// We use this information for multiple DPI support + clamping the position of popups and tooltips so they don't straddle multiple monitors.
@ -2405,65 +2511,7 @@ struct ImGuiPlatformMonitor
ImVec2 MainPos, MainSize; // Coordinates of the area displayed on this monitor (Min = upper left, Max = bottom right)
ImVec2 WorkPos, WorkSize; // (Optional) Coordinates without task bars / side bars / menu bars. imgui uses this to avoid positioning popups/tooltips inside this region.
float DpiScale; // 1.0f = 96 DPI
ImGuiPlatformMonitor() { MainPos = MainSize = WorkPos = WorkSize = ImVec2(0,0); DpiScale = 1.0f; }
};
// (Optional) Setup required only if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) is enabled.
// Access via ImGui::GetPlatformIO(). This is designed so we can mix and match two imgui_impl_xxxx files,
// one for the Platform (~window handling), one for Renderer. Custom engine back-ends will often provide
// both Platform and Renderer interfaces and so may not need to use all functions.
// Platform functions are typically called before their Renderer counterpart,
// apart from Destroy which are called the other way.
// RenderPlatformWindowsDefault() is that helper that iterate secondary viewports and call, in this order:
// Platform_RenderWindow(), Renderer_RenderWindow(), Platform_SwapBuffers(), Renderer_SwapBuffers()
// You may skip using RenderPlatformWindowsDefault() and call your draw/swap functions yourself if you need
// specific behavior for your multi-window rendering.
struct ImGuiPlatformIO
{
//------------------------------------------------------------------
// Input - Back-end interface/functions + Monitor List
//------------------------------------------------------------------
// (Optional) Platform functions (e.g. Win32, GLFW, SDL2)
// Most of them are called by ImGui::UpdatePlatformWindows() and ImGui::RenderPlatformWindowsDefault().
void (*Platform_CreateWindow)(ImGuiViewport* vp); // Create a new platform window for the given viewport
void (*Platform_DestroyWindow)(ImGuiViewport* vp);
void (*Platform_ShowWindow)(ImGuiViewport* vp); // Newly created windows are initially hidden so SetWindowPos/Size/Title can be called on them first
void (*Platform_SetWindowPos)(ImGuiViewport* vp, ImVec2 pos);
ImVec2 (*Platform_GetWindowPos)(ImGuiViewport* vp);
void (*Platform_SetWindowSize)(ImGuiViewport* vp, ImVec2 size);
ImVec2 (*Platform_GetWindowSize)(ImGuiViewport* vp);
void (*Platform_SetWindowFocus)(ImGuiViewport* vp); // Move window to front and set input focus
bool (*Platform_GetWindowFocus)(ImGuiViewport* vp);
bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp);
void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* title);
void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // (Optional) Setup window transparency
void (*Platform_UpdateWindow)(ImGuiViewport* vp); // (Optional) Called in UpdatePlatforms(). Optional hook to allow the platform back-end from doing general book-keeping every frame.
void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Setup for render
void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (platform side)
float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // (Optional) [BETA] (FIXME-DPI) DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI.
void (*Platform_OnChangedViewport)(ImGuiViewport* vp); // (Optional) [BETA] (FIXME-DPI) DPI handling: Called during Begin() every time the viewport we are outputting into changes, so back-end has a chance to swap fonts to adjust style.
void (*Platform_SetImeInputPos)(ImGuiViewport* vp, ImVec2 pos); // (Optional) Set IME (Input Method Editor, e.g. for Asian languages) input position, so text preview appears over the imgui input box.
int (*Platform_CreateVkSurface)(ImGuiViewport* vp, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); // (Optional) For Renderer to call into Platform code
// (Optional) Renderer functions (e.g. DirectX, OpenGL3, Vulkan)
void (*Renderer_CreateWindow)(ImGuiViewport* vp); // Create swap chains, frame buffers etc.
void (*Renderer_DestroyWindow)(ImGuiViewport* vp);
void (*Renderer_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // Resize swap chain, frame buffers etc.
void (*Renderer_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Clear targets, Render viewport->DrawData
void (*Renderer_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (renderer side)
// (Optional) List of monitors (updated by: app/back-end, used by: imgui to clamp popups/tooltips within same monitor and not have them straddle monitors)
ImVector<ImGuiPlatformMonitor> Monitors;
//------------------------------------------------------------------
// Output - List of viewports to render into platform windows
//------------------------------------------------------------------
// List of viewports (the list is updated by calling ImGui::EndFrame or ImGui::Render)
ImGuiViewport* MainViewport; // Guaranteed to be == Viewports[0]
ImVector<ImGuiViewport*> Viewports; // Main viewports, followed by all secondary viewports.
ImGuiPlatformIO() { memset(this, 0, sizeof(*this)); } // Zero clear
ImGuiPlatformMonitor() { MainPos = MainSize = WorkPos = WorkSize = ImVec2(0, 0); DpiScale = 1.0f; }
};
// Flags stored in ImGuiViewport::Flags, giving indications to the platform back-ends.
@ -2498,9 +2546,11 @@ struct ImGuiViewport
ImGuiID ParentViewportId; // (Advanced) 0: no parent. Instruct the platform back-end to setup a parent/child relationship between platform windows.
// Our design separate the Renderer and Platform back-ends to facilitate combining default back-ends with each others.
// When our create your own back-end for a custom engine, it is possible that both Renderer and Platform will be handled by the same system and you may not need to use all the UserData/Handle fields.
void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, framebuffers etc.).
void* PlatformUserData; // void* to hold custom data structure for the OS / platform (e.g. windowing info, render context).
// When our create your own back-end for a custom engine, it is possible that both Renderer and Platform will be handled
// by the same system and you may not need to use all the UserData/Handle fields.
// The library never uses those fields, they are merely storage to facilitate back-end implementation.
void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, framebuffers etc.). generally set by your Renderer_CreateWindow function.
void* PlatformUserData; // void* to hold custom data structure for the OS / platform (e.g. windowing info, render context). generally set by your Platform_CreateWindow function.
void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. suggested to use natural platform handle such as HWND, GLFWWindow*, SDL_Window*)
void* PlatformHandleRaw; // void* to hold lower-level, platform-native window handle (e.g. the HWND) when using an abstraction layer like GLFW or SDL (where PlatformHandle would be a SDL_Window*)
bool PlatformRequestMove; // Platform window requested move (e.g. window was moved by the OS / host window manager, authoritative position will be OS window position)