Viewport: per-viewport overlay draw list created on demand. With this pattern it'll be easier to consider adding more (e.g. background draw list). (#545)

This commit is contained in:
omar 2018-04-11 13:04:29 +02:00
parent 83bd3595a4
commit 8be6f40ae1
2 changed files with 40 additions and 33 deletions

View File

@ -2717,17 +2717,32 @@ int ImGui::GetFrameCount()
return GImGui->FrameCount; return GImGui->FrameCount;
} }
ImDrawList* ImGui::GetOverlayDrawList(ImGuiWindow* window) ImDrawList* ImGui::GetOverlayDrawList(ImGuiViewportP* viewport)
{ {
IM_ASSERT(window && window->Viewport); // Create the draw list on demand, because it is not frequently used for all viewports
return window->Viewport->OverlayDrawList; ImGuiContext& g = *GImGui;
if (viewport->OverlayDrawList == NULL)
{
viewport->OverlayDrawList = IM_NEW(ImDrawList)(&g.DrawListSharedData);
viewport->OverlayDrawList->_OwnerName = "##Overlay";
}
// Our ImDrawList system requires that there is always a command
if (viewport->LastFrameOverlayDrawList != g.FrameCount)
{
viewport->OverlayDrawList->Clear();
viewport->OverlayDrawList->PushTextureID(g.IO.Fonts->TexID);
viewport->OverlayDrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->OverlayDrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
viewport->LastFrameOverlayDrawList = g.FrameCount;
}
return viewport->OverlayDrawList;
} }
ImDrawList* ImGui::GetOverlayDrawList() ImDrawList* ImGui::GetOverlayDrawList()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;
IM_ASSERT(window && window->Viewport); return GetOverlayDrawList(window->Viewport);
return window->Viewport->OverlayDrawList;
} }
ImDrawListSharedData* ImGui::GetDrawListSharedData() ImDrawListSharedData* ImGui::GetDrawListSharedData()
@ -3633,15 +3648,6 @@ void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* render
} }
} }
static void SetupOverlayDrawList(ImDrawList* draw_list, ImGuiViewport* viewport)
{
ImGuiContext& g = *GImGui;
draw_list->Clear();
draw_list->PushTextureID(g.IO.Fonts->TexID);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
draw_list->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
}
static void NewFrameUpdateMouseInputs() static void NewFrameUpdateMouseInputs()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -3832,7 +3838,6 @@ void ImGui::NewFrame()
ImGuiViewportP* viewport = g.Viewports[n]; ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawData = NULL; viewport->DrawData = NULL;
viewport->DrawDataP.Clear(); viewport->DrawDataP.Clear();
SetupOverlayDrawList(viewport->OverlayDrawList, viewport);
} }
// Clear reference to active widget if the widget isn't alive anymore // Clear reference to active widget if the widget isn't alive anymore
@ -4051,7 +4056,7 @@ void ImGui::Initialize(ImGuiContext* context)
g.SettingsHandlers.push_front(ini_handler); g.SettingsHandlers.push_front(ini_handler);
// Create default viewport // Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(&g.DrawListSharedData); ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID; viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID;
viewport->Idx = 0; viewport->Idx = 0;
g.Viewports.push_back(viewport); g.Viewports.push_back(viewport);
@ -4563,7 +4568,7 @@ void ImGui::Render()
ImVec2 pos = (g.MousePosViewport == viewport) ? main_pos : ConvertPlatformPosToViewportPos(ConvertViewportPosToPlatformPos(main_pos, g.MousePosViewport), viewport); ImVec2 pos = (g.MousePosViewport == viewport) ? main_pos : ConvertPlatformPosToViewportPos(ConvertViewportPosToPlatformPos(main_pos, g.MousePosViewport), viewport);
if (viewport->GetRect().Overlaps(ImRect(pos, pos + ImVec2(2,2)*sc + size * sc))) if (viewport->GetRect().Overlaps(ImRect(pos, pos + ImVec2(2,2)*sc + size * sc)))
{ {
ImDrawList* draw_list = viewport->OverlayDrawList; ImDrawList* draw_list = GetOverlayDrawList(viewport);
draw_list->PushTextureID(tex_id); draw_list->PushTextureID(tex_id);
draw_list->AddImage(tex_id, pos+ImVec2(1,0)*sc, pos+ImVec2(1,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow draw_list->AddImage(tex_id, pos+ImVec2(1,0)*sc, pos+ImVec2(1,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow
draw_list->AddImage(tex_id, pos+ImVec2(2,0)*sc, pos+ImVec2(2,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow draw_list->AddImage(tex_id, pos+ImVec2(2,0)*sc, pos+ImVec2(2,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow
@ -4580,7 +4585,8 @@ void ImGui::Render()
{ {
ImGuiViewportP* viewport = g.Viewports[n]; ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawDataBuilder.FlattenIntoSingleLayer(); viewport->DrawDataBuilder.FlattenIntoSingleLayer();
AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], viewport->OverlayDrawList); if (viewport->OverlayDrawList != NULL)
AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetOverlayDrawList(viewport));
SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]); SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]);
g.IO.MetricsRenderVertices += viewport->DrawData->TotalVtxCount; g.IO.MetricsRenderVertices += viewport->DrawData->TotalVtxCount;
g.IO.MetricsRenderIndices += viewport->DrawData->TotalIdxCount; g.IO.MetricsRenderIndices += viewport->DrawData->TotalIdxCount;
@ -4683,7 +4689,7 @@ ImGuiViewportP* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFl
else else
{ {
// New viewport // New viewport
viewport = IM_NEW(ImGuiViewportP)(&g.DrawListSharedData); viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = id; viewport->ID = id;
viewport->Idx = g.Viewports.Size; viewport->Idx = g.Viewports.Size;
viewport->Pos = ImVec2(g.Viewports.back()->GetNextX(), 0.0f); viewport->Pos = ImVec2(g.Viewports.back()->GetNextX(), 0.0f);
@ -4691,11 +4697,9 @@ ImGuiViewportP* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFl
g.Viewports.push_back(viewport); g.Viewports.push_back(viewport);
// We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport. // We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport.
// 1. We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame // We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame
// 2. Our ImDrawList system requires that there is always a command, SetupOverlayDrawList() effectively does that by setting up texture and clip rect
g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x); 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); g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
SetupOverlayDrawList(viewport->OverlayDrawList, viewport);
} }
IM_ASSERT(viewport->Pos.y == 0.0f); IM_ASSERT(viewport->Pos.y == 0.0f);
@ -6699,11 +6703,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Draw modal window background (darkens what is behind them, all viewports) // Draw modal window background (darkens what is behind them, all viewports)
if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow() && window->HiddenFrames <= 0) if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow() && window->HiddenFrames <= 0)
{
window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio));
for (int viewport_n = 0; viewport_n < g.Viewports.Size; viewport_n++) for (int viewport_n = 0; viewport_n < g.Viewports.Size; viewport_n++)
if (g.Viewports[viewport_n] != window->Viewport) {
g.Viewports[viewport_n]->OverlayDrawList->AddRectFilled(g.Viewports[viewport_n]->Pos, g.Viewports[viewport_n]->Pos + g.Viewports[viewport_n]->Size, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); ImGuiViewportP* viewport = g.Viewports[viewport_n];
ImDrawList* draw_list = (viewport == window->Viewport) ? window->DrawList : GetOverlayDrawList(viewport);
draw_list->AddRectFilled(viewport->Pos, viewport->Pos + viewport->Size, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio));
} }
// Draw navigation selection/windowing rectangle background // Draw navigation selection/windowing rectangle background
@ -14060,7 +14064,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return; return;
} }
ImDrawList* overlay_draw_list = viewport->OverlayDrawList; // Render additional visuals into the top-most draw list ImDrawList* overlay_draw_list = GetOverlayDrawList(viewport); // Render additional visuals into the top-most draw list
if (window && ImGui::IsItemHovered()) if (window && ImGui::IsItemHovered())
overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
if (!node_open) if (!node_open)
@ -14245,8 +14249,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
char buf[32]; char buf[32];
ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext); ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
float font_size = ImGui::GetFontSize() * 2; float font_size = ImGui::GetFontSize() * 2;
window->Viewport->OverlayDrawList->AddRectFilled(window->PosFloat, window->PosFloat + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255)); ImDrawList* overlay_draw_list = GetOverlayDrawList(window->Viewport);
window->Viewport->OverlayDrawList->AddText(NULL, font_size, window->PosFloat, IM_COL32(255, 255, 255, 255), buf); overlay_draw_list->AddRectFilled(window->PosFloat, window->PosFloat + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
overlay_draw_list->AddText(NULL, font_size, window->PosFloat, IM_COL32(255, 255, 255, 255), buf);
} }
} }
} }

View File

@ -516,6 +516,7 @@ struct ImGuiViewportP : public ImGuiViewport
int Idx; int Idx;
int LastFrameActive; // Last frame number this viewport was activated by a window int LastFrameActive; // Last frame number this viewport was activated by a window
int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef
int LastFrameOverlayDrawList;
ImGuiID LastNameHash; ImGuiID LastNameHash;
float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent) float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent)
float LastAlpha; float LastAlpha;
@ -525,8 +526,8 @@ struct ImGuiViewportP : public ImGuiViewport
ImDrawDataBuilder DrawDataBuilder; ImDrawDataBuilder DrawDataBuilder;
ImVec2 RendererLastSize; ImVec2 RendererLastSize;
ImGuiViewportP(ImDrawListSharedData* draw_list_shared_data) { Idx = 1; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; Window = NULL; OverlayDrawList = IM_NEW(ImDrawList)(draw_list_shared_data); OverlayDrawList->_OwnerName = "##Overlay"; RendererLastSize = ImVec2(-1.0f,-1.0f); } ImGuiViewportP() { Idx = 1; LastFrameActive = LastFrameAsRefViewport = LastFrameOverlayDrawList = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; Window = NULL; OverlayDrawList = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); }
~ImGuiViewportP() { IM_DELETE(OverlayDrawList); } ~ImGuiViewportP() { if (OverlayDrawList) IM_DELETE(OverlayDrawList); }
ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; } float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; }
}; };
@ -1099,7 +1100,8 @@ namespace ImGui
IMGUI_API void PopItemFlag(); IMGUI_API void PopItemFlag();
IMGUI_API void SetCurrentFont(ImFont* font); IMGUI_API void SetCurrentFont(ImFont* font);
IMGUI_API ImDrawList* GetOverlayDrawList(ImGuiWindow* window); IMGUI_API ImDrawList* GetOverlayDrawList(ImGuiViewportP* viewport);
inline ImDrawList* GetOverlayDrawList(ImGuiWindow* window) { return GetOverlayDrawList(window->Viewport); }
IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void OpenPopupEx(ImGuiID id);
IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API void ClosePopup(ImGuiID id);