Refactor: Internals: Moved Viewport functions in imgui.cpp in their own section. (part 3) (#2036, #1542)

This commit is contained in:
omar 2018-08-31 11:08:48 +02:00
parent 5207afa0dd
commit fd90afef43

320
imgui.cpp
View File

@ -56,6 +56,7 @@ CODE
- Main Code (most of the code! lots of stuff, needs tidying up)
- Tooltips
- Popups
- Viewports, Platform Windows
- Navigation
- Columns
- Drag and Drop
@ -911,7 +912,6 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx,
// Platform Dependents default implementation for IO functions
static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
namespace ImGui
{
@ -3582,53 +3582,6 @@ void ImGui::Render()
#endif
}
ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0);
ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id);
if (viewport)
{
viewport->Pos = pos;
viewport->Size = size;
}
else
{
// New viewport
viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = id;
viewport->Idx = g.Viewports.Size;
viewport->Pos = viewport->LastPos = pos;
viewport->Size = size;
viewport->PlatformMonitor = FindPlatformMonitorForRect(viewport->GetRect());
g.Viewports.push_back(viewport);
if (window && (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing))
flags |= ImGuiViewportFlags_NoFocusOnAppearing;
// We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport.
// We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame
g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
// Request an initial DpiScale before the OS platform window creation
// This is so we can select an appropriate font size on the first frame of our window lifetime
if (g.PlatformIO.Platform_GetWindowDpiScale)
viewport->DpiScale = g.PlatformIO.Platform_GetWindowDpiScale(viewport);
}
viewport->Window = window;
viewport->Flags = flags;
viewport->LastFrameActive = g.FrameCount;
IM_ASSERT(window == NULL || viewport->ID == window->ID);
if (window != NULL)
window->ViewportOwned = true;
return viewport;
}
const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
{
const char* text_display_end = text;
@ -4636,118 +4589,6 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect)
return best_monitor_n;
}
// FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten.
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags;
window->ViewportAllowPlatformMonitorExtend = -1;
// Restore main viewport if multi-viewport is not supported by the back-end
ImGuiViewportP* main_viewport = g.Viewports[0];
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
{
window->Viewport = main_viewport;
window->ViewportId = main_viewport->ID;
window->ViewportOwned = false;
return;
}
// Merge into host viewports (after moving, resizing)
if (window->ViewportOwned && window->ViewportTryMerge && g.ActiveId == 0)
{
UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]);
window->ViewportTryMerge = false;
}
window->ViewportOwned = false;
// Appearing popups reset their viewport so they can inherit again
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
{
window->Viewport = NULL;
window->ViewportId = 0;
}
if (!g.NextWindowData.ViewportCond)
{
// By default inherit from parent window
if (window->Viewport == NULL && window->ParentWindow)
window->Viewport = window->ParentWindow->Viewport;
// 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);
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_NoDecoration);
}
}
if (g.NextWindowData.ViewportCond)
{
// Code explicitly request a viewport
window->Viewport = 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))
{
// Always inherit viewport from parent window
window->Viewport = window->ParentWindow->Viewport;
}
else if (flags & ImGuiWindowFlags_Tooltip)
{
window->Viewport = g.MouseViewport;
}
else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid())
{
// Transition to our own viewport when leaving our host boundaries + set the NoInputs flag (which will be cleared in UpdateMovingWindow when releasing the mouse)
// If we are already in our own viewport, if need to set the NoInputs flag.
// If we have no viewport (which happens when detaching a docked node) immediately create one.
// We test for 'window->Viewport->Window == window' instead of 'window->ViewportOwned' because ViewportOwned is not valid during this function.
bool has_viewport = (window->Viewport != NULL);
bool own_viewport = has_viewport && (window->Viewport->Window == window);
bool leave_host_viewport = has_viewport && !own_viewport && !window->Viewport->GetRect().Contains(window->Rect());
bool move_from_own_viewport = has_viewport && own_viewport && !(window->Viewport->Flags & ImGuiViewportFlags_NoInputs);
if (!has_viewport || leave_host_viewport || move_from_own_viewport)
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs);
}
else if (GetWindowAlwaysWantOwnViewport(window))
{
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration);
}
// Mark window as allowed to protrude outside of its viewport and into the current monitor
// We need to take account of the possibility that mouse may become invalid.
const bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow);
if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
{
ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.CurrentPopupStack.back().OpenMousePos;
bool mouse_valid = IsMousePosValid(&mouse_ref);
if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid))
window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
else
window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
}
if (window->ViewportTrySplit && window->ViewportAllowPlatformMonitorExtend < 0)
window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
window->ViewportTrySplit = false;
// Fallback to default viewport
if (window->Viewport == NULL)
window->Viewport = main_viewport;
// Update flags
window->ViewportOwned = (window == window->Viewport->Window);
if (window->ViewportOwned)
window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration;
// If the OS window has a title bar, hide our imgui title bar
if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
window->Flags |= ImGuiWindowFlags_NoTitleBar;
window->ViewportId = window->Viewport->ID;
}
struct ImGuiResizeGripDef
{
ImVec2 CornerPos;
@ -7619,6 +7460,165 @@ static void ImGui::UpdateViewports()
IM_ASSERT(g.MouseViewport != NULL);
}
ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0);
ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id);
if (viewport)
{
viewport->Pos = pos;
viewport->Size = size;
}
else
{
// New viewport
viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = id;
viewport->Idx = g.Viewports.Size;
viewport->Pos = viewport->LastPos = pos;
viewport->Size = size;
viewport->PlatformMonitor = FindPlatformMonitorForRect(viewport->GetRect());
g.Viewports.push_back(viewport);
if (window && (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing))
flags |= ImGuiViewportFlags_NoFocusOnAppearing;
// We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport.
// We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame
g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
// Request an initial DpiScale before the OS platform window creation
// This is so we can select an appropriate font size on the first frame of our window lifetime
if (g.PlatformIO.Platform_GetWindowDpiScale)
viewport->DpiScale = g.PlatformIO.Platform_GetWindowDpiScale(viewport);
}
viewport->Window = window;
viewport->Flags = flags;
viewport->LastFrameActive = g.FrameCount;
IM_ASSERT(window == NULL || viewport->ID == window->ID);
if (window != NULL)
window->ViewportOwned = true;
return viewport;
}
// FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten.
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags;
window->ViewportAllowPlatformMonitorExtend = -1;
// Restore main viewport if multi-viewport is not supported by the back-end
ImGuiViewportP* main_viewport = g.Viewports[0];
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
{
window->Viewport = main_viewport;
window->ViewportId = main_viewport->ID;
window->ViewportOwned = false;
return;
}
// Merge into host viewports (after moving, resizing)
if (window->ViewportOwned && window->ViewportTryMerge && g.ActiveId == 0)
{
UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]);
window->ViewportTryMerge = false;
}
window->ViewportOwned = false;
// Appearing popups reset their viewport so they can inherit again
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
{
window->Viewport = NULL;
window->ViewportId = 0;
}
if (!g.NextWindowData.ViewportCond)
{
// By default inherit from parent window
if (window->Viewport == NULL && window->ParentWindow)
window->Viewport = window->ParentWindow->Viewport;
// 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);
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_NoDecoration);
}
}
if (g.NextWindowData.ViewportCond)
{
// Code explicitly request a viewport
window->Viewport = 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))
{
// Always inherit viewport from parent window
window->Viewport = window->ParentWindow->Viewport;
}
else if (flags & ImGuiWindowFlags_Tooltip)
{
window->Viewport = g.MouseViewport;
}
else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid())
{
// Transition to our own viewport when leaving our host boundaries + set the NoInputs flag (which will be cleared in UpdateMovingWindow when releasing the mouse)
// If we are already in our own viewport, if need to set the NoInputs flag.
// If we have no viewport (which happens when detaching a docked node) immediately create one.
// We test for 'window->Viewport->Window == window' instead of 'window->ViewportOwned' because ViewportOwned is not valid during this function.
bool has_viewport = (window->Viewport != NULL);
bool own_viewport = has_viewport && (window->Viewport->Window == window);
bool leave_host_viewport = has_viewport && !own_viewport && !window->Viewport->GetRect().Contains(window->Rect());
bool move_from_own_viewport = has_viewport && own_viewport && !(window->Viewport->Flags & ImGuiViewportFlags_NoInputs);
if (!has_viewport || leave_host_viewport || move_from_own_viewport)
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs);
}
else if (GetWindowAlwaysWantOwnViewport(window))
{
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration);
}
// Mark window as allowed to protrude outside of its viewport and into the current monitor
// We need to take account of the possibility that mouse may become invalid.
const bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow);
if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
{
ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.CurrentPopupStack.back().OpenMousePos;
bool mouse_valid = IsMousePosValid(&mouse_ref);
if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid))
window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
else
window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
}
if (window->ViewportTrySplit && window->ViewportAllowPlatformMonitorExtend < 0)
window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
window->ViewportTrySplit = false;
// Fallback to default viewport
if (window->Viewport == NULL)
window->Viewport = main_viewport;
// Update flags
window->ViewportOwned = (window == window->Viewport->Window);
if (window->ViewportOwned)
window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration;
// If the OS window has a title bar, hide our imgui title bar
if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
window->Flags |= ImGuiWindowFlags_NoTitleBar;
window->ViewportId = window->Viewport->ID;
}
void ImGui::UpdatePlatformWindows()
{
ImGuiContext& g = *GImGui;