Update ImGui to docking@5d472c489.

This commit is contained in:
Bartosz Taudul 2020-06-05 19:21:07 +02:00
parent 16b116ee83
commit de357b6193
7 changed files with 681 additions and 551 deletions

View File

@ -921,7 +921,6 @@ static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For u
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static void SetCurrentWindow(ImGuiWindow* window); static void SetCurrentWindow(ImGuiWindow* window);
static void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
static void FindHoveredWindow(); static void FindHoveredWindow();
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags); static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
@ -931,9 +930,9 @@ static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted
// Settings // Settings
static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*); static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name); static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line); static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf); static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
// Platform Dependents default implementation for IO functions // Platform Dependents default implementation for IO functions
@ -949,6 +948,7 @@ static void NavUpdateWindowingOverlay();
static void NavUpdateMoveResult(); static void NavUpdateMoveResult();
static float NavUpdatePageUpPageDown(); static float NavUpdatePageUpPageDown();
static inline void NavUpdateAnyRequestFlag(); static inline void NavUpdateAnyRequestFlag();
static void NavEndFrame();
static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand); static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand);
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
static ImVec2 NavCalcPreferredRefPos(); static ImVec2 NavCalcPreferredRefPos();
@ -1178,17 +1178,21 @@ ImGuiIO::ImGuiIO()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(unsigned int c) void ImGuiIO::AddInputCharacter(unsigned int c)
{ {
InputQueueCharacters.push_back(c > 0 && c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); if (c != 0)
InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
} }
// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so // UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
// we should save the high surrogate. // we should save the high surrogate.
void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
{ {
if (c == 0 && InputQueueSurrogate == 0)
return;
if ((c & 0xFC00) == 0xD800) // High surrogate, must save if ((c & 0xFC00) == 0xD800) // High surrogate, must save
{ {
if (InputQueueSurrogate != 0) if (InputQueueSurrogate != 0)
InputQueueCharacters.push_back(0xFFFD); InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
InputQueueSurrogate = c; InputQueueSurrogate = c;
return; return;
} }
@ -1213,7 +1217,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
{ {
unsigned int c = 0; unsigned int c = 0;
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
if (c > 0) if (c != 0)
InputQueueCharacters.push_back((ImWchar)c); InputQueueCharacters.push_back((ImWchar)c);
} }
} }
@ -4133,9 +4137,9 @@ void ImGui::Initialize(ImGuiContext* context)
ini_handler.TypeName = "Window"; ini_handler.TypeName = "Window";
ini_handler.TypeHash = ImHashStr("Window"); ini_handler.TypeHash = ImHashStr("Window");
ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll; ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen; ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine; ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll; ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
g.SettingsHandlers.push_back(ini_handler); g.SettingsHandlers.push_back(ini_handler);
} }
@ -4164,7 +4168,6 @@ void ImGui::Initialize(ImGuiContext* context)
g.PlatformIO.Viewports.push_back(g.Viewports[0]); g.PlatformIO.Viewports.push_back(g.Viewports[0]);
// Extensions // Extensions
IM_ASSERT(g.DockContext == NULL);
DockContextInitialize(&g); DockContextInitialize(&g);
#endif // #ifdef IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK
@ -4203,7 +4206,6 @@ void ImGui::Shutdown(ImGuiContext* context)
SetCurrentContext(backup_context); SetCurrentContext(backup_context);
// Shutdown extensions // Shutdown extensions
IM_ASSERT(g.DockContext != NULL);
DockContextShutdown(&g); DockContextShutdown(&g);
// Clear everything else // Clear everything else
@ -4365,6 +4367,13 @@ void ImDrawDataBuilder::FlattenIntoSingleLayer()
static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*>* draw_lists) static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*>* draw_lists)
{ {
// When minimized, we report draw_data->DisplaySize as zero to be consistent with non-viewport mode,
// and to allow applications/back-ends to easily skip rendering.
// FIXME: Note that we however do NOT attempt to report "zero drawlist / vertices" into the ImDrawData structure.
// This is because the work has been done already, and its wasted! We should fix that and add optimizations for
// it earlier in the pipeline, rather than pretend to hide the data at the end of the pipeline.
const bool is_minimized = (viewport->Flags & ImGuiViewportFlags_Minimized) != 0;
ImDrawData* draw_data = &viewport->DrawDataP; ImDrawData* draw_data = &viewport->DrawDataP;
viewport->DrawData = draw_data; // Make publicly accessible viewport->DrawData = draw_data; // Make publicly accessible
draw_data->Valid = true; draw_data->Valid = true;
@ -4372,7 +4381,7 @@ static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*
draw_data->CmdListsCount = draw_lists->Size; draw_data->CmdListsCount = draw_lists->Size;
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
draw_data->DisplayPos = viewport->Pos; draw_data->DisplayPos = viewport->Pos;
draw_data->DisplaySize = viewport->Size; draw_data->DisplaySize = is_minimized ? ImVec2(0.0f, 0.0f) : viewport->Size;
draw_data->FramebufferScale = ImGui::GetIO().DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis? draw_data->FramebufferScale = ImGui::GetIO().DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis?
draw_data->OwnerViewport = viewport; draw_data->OwnerViewport = viewport;
for (int n = 0; n < draw_lists->Size; n++) for (int n = 0; n < draw_lists->Size; n++)
@ -4419,7 +4428,7 @@ static void ImGui::EndFrameDrawDimmedBackgrounds()
ImGuiViewportP* viewport = g.Viewports[viewport_n]; ImGuiViewportP* viewport = g.Viewports[viewport_n];
if (modal_window && viewport == modal_window->Viewport) if (modal_window && viewport == modal_window->Viewport)
continue; continue;
if (g.NavWindowingList && viewport == g.NavWindowingList->Viewport) if (g.NavWindowingListWindow && viewport == g.NavWindowingListWindow->Viewport)
continue; continue;
if (g.NavWindowingTargetAnim && viewport == g.NavWindowingTargetAnim->Viewport) if (g.NavWindowingTargetAnim && viewport == g.NavWindowingTargetAnim->Viewport)
continue; continue;
@ -4486,9 +4495,8 @@ void ImGui::EndFrame()
// Draw modal whitening background on _other_ viewports than the one the modal is one // Draw modal whitening background on _other_ viewports than the one the modal is one
EndFrameDrawDimmedBackgrounds(); EndFrameDrawDimmedBackgrounds();
// Show CTRL+TAB list window // Update navigation: CTRL+Tab, wrap-around requests
if (g.NavWindowingTarget != NULL) NavEndFrame();
NavUpdateWindowingOverlay();
SetCurrentViewport(NULL, NULL); SetCurrentViewport(NULL, NULL);
@ -4567,7 +4575,7 @@ void ImGui::Render()
// Add ImDrawList to render // Add ImDrawList to render
ImGuiWindow* windows_to_render_top_most[2]; ImGuiWindow* windows_to_render_top_most[2];
windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingList : NULL); windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
for (int n = 0; n != g.Windows.Size; n++) for (int n = 0; n != g.Windows.Size; n++)
{ {
ImGuiWindow* window = g.Windows[n]; ImGuiWindow* window = g.Windows[n];
@ -5415,6 +5423,21 @@ static const ImGuiResizeGripDef resize_grip_def[4] =
{ ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper-right (Unused) { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper-right (Unused)
}; };
struct ImGuiResizeBorderDef
{
ImVec2 InnerDir;
ImVec2 CornerPosN1, CornerPosN2;
float OuterAngle;
};
static const ImGuiResizeBorderDef resize_border_def[4] =
{
{ ImVec2(0,+1), ImVec2(0,0), ImVec2(1,0), IM_PI*1.50f }, // Top
{ ImVec2(-1,0), ImVec2(1,0), ImVec2(1,1), IM_PI*0.00f }, // Right
{ ImVec2(0,-1), ImVec2(1,1), ImVec2(0,1), IM_PI*0.50f }, // Bottom
{ ImVec2(+1,0), ImVec2(0,1), ImVec2(0,0), IM_PI*1.00f } // Left
};
static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness) static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
{ {
ImRect rect = window->Rect(); ImRect rect = window->Rect();
@ -5591,19 +5614,6 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
int border_held = window->ResizeBorderHeld; int border_held = window->ResizeBorderHeld;
if (border_held != -1) if (border_held != -1)
{ {
struct ImGuiResizeBorderDef
{
ImVec2 InnerDir;
ImVec2 CornerPosN1, CornerPosN2;
float OuterAngle;
};
static const ImGuiResizeBorderDef resize_border_def[4] =
{
{ ImVec2(0,+1), ImVec2(0,0), ImVec2(1,0), IM_PI*1.50f }, // Top
{ ImVec2(-1,0), ImVec2(1,0), ImVec2(1,1), IM_PI*0.00f }, // Right
{ ImVec2(0,-1), ImVec2(1,1), ImVec2(0,1), IM_PI*0.50f }, // Bottom
{ ImVec2(+1,0), ImVec2(0,1), ImVec2(0,0), IM_PI*1.00f } // Left
};
const ImGuiResizeBorderDef& def = resize_border_def[border_held]; const ImGuiResizeBorderDef& def = resize_border_def[border_held];
ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f); ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI*0.25f, def.OuterAngle); window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI*0.25f, def.OuterAngle);
@ -6030,7 +6040,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
bool window_title_visible_elsewhere = false; bool window_title_visible_elsewhere = false;
if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive)) if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
window_title_visible_elsewhere = true; window_title_visible_elsewhere = true;
else if (g.NavWindowingList != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB else if (g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
window_title_visible_elsewhere = true; window_title_visible_elsewhere = true;
if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0) if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
{ {
@ -6236,7 +6246,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
UpdateViewportPlatformMonitor(window->Viewport); UpdateViewportPlatformMonitor(window->Viewport);
// Update common viewport flags // Update common viewport flags
ImGuiViewportFlags viewport_flags = (window->Viewport->Flags) & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration); const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
const bool is_short_lived_floating_window = (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0; const bool is_short_lived_floating_window = (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
if (flags & ImGuiWindowFlags_Tooltip) if (flags & ImGuiWindowFlags_Tooltip)
viewport_flags |= ImGuiViewportFlags_TopMost; viewport_flags |= ImGuiViewportFlags_TopMost;
@ -6266,7 +6277,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear; viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
// 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 // 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; if (!(flags & ImGuiWindowFlags_NoBackground))
viewport_flags &= ~ImGuiViewportFlags_NoRendererClear;
window->Viewport->Flags = viewport_flags; window->Viewport->Flags = viewport_flags;
} }
@ -6427,8 +6440,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
PushClipRect(host_rect.Min, host_rect.Max, false); PushClipRect(host_rect.Min, host_rect.Max, false);
// Draw modal or window list full viewport dimming background (for other viewports we'll render them in EndFrame) // Draw modal or window list full viewport dimming background (for other viewports we'll render them in EndFrame)
ImGuiWindow* window_window_list = g.NavWindowingListWindow;
const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0;
const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindow) || (g.NavWindowingList && (window == g.NavWindowingList) && g.NavWindowingList->Viewport != g.NavWindowingTargetAnim->Viewport)); const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindow) || (window == window_window_list && window_window_list->Viewport != g.NavWindowingTargetAnim->Viewport));
if (dim_bg_for_modal || dim_bg_for_window_list) if (dim_bg_for_modal || dim_bg_for_window_list)
{ {
const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio); const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
@ -6791,24 +6805,28 @@ void ImGui::FocusWindow(ImGuiWindow* window)
// Close popups if any // Close popups if any
ClosePopupsOverWindow(window, false); ClosePopupsOverWindow(window, false);
// Move the root window to the top of the pile
IM_ASSERT(window == NULL || window->RootWindow != NULL);
ImGuiWindow* focus_front_window = window ? window->RootWindowDockStop : NULL;
ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
// Steal active widgets. Some of the cases it triggers includes:
// - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run.
// - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId)
// - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window.
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindowDockStop != focus_front_window && !active_id_window_is_dock_node_host)
ClearActiveID();
// Passing NULL allow to disable keyboard focus // Passing NULL allow to disable keyboard focus
if (!window) if (!window)
return; return;
window->LastFrameJustFocused = g.FrameCount; window->LastFrameJustFocused = g.FrameCount;
// Select in dock node // Select in dock node
if (window->DockNode && window->DockNode->TabBar) if (dock_node && dock_node->TabBar)
window->DockNode->TabBar->SelectedTabId = window->DockNode->TabBar->NextSelectedTabId = window->ID; dock_node->TabBar->SelectedTabId = dock_node->TabBar->NextSelectedTabId = window->ID;
// Move the root window to the top of the pile
IM_ASSERT(window->RootWindow != NULL);
ImGuiWindow* focus_front_window = window->RootWindowDockStop;
ImGuiWindow* display_front_window = window->RootWindow;
// Steal focus on active widgets
if (focus_front_window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement may be unnecessary? Need further testing before removing it..
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
ClearActiveID();
// Bring to front // Bring to front
BringWindowToFocusFront(focus_front_window); BringWindowToFocusFront(focus_front_window);
@ -7136,7 +7154,7 @@ void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond co
window->Collapsed = collapsed; window->Collapsed = collapsed;
} }
static void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size) void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size)
{ {
IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters
window->HitTestHoleSize = ImVec2ih(size); window->HitTestHoleSize = ImVec2ih(size);
@ -7323,6 +7341,7 @@ void ImGui::ActivateItem(ImGuiID id)
g.NavNextActivateId = id; g.NavNextActivateId = id;
} }
// Note: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there.
void ImGui::PushFocusScope(ImGuiID id) void ImGui::PushFocusScope(ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -8561,7 +8580,8 @@ void ImGui::EndPopup()
IM_ASSERT(g.BeginPopupStack.Size > 0); IM_ASSERT(g.BeginPopupStack.Size > 0);
// Make all menus and popups wrap around for now, may need to expose that policy. // Make all menus and popups wrap around for now, may need to expose that policy.
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY); if (g.NavWindow == window)
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
// Child-popups don't need to be laid out // Child-popups don't need to be laid out
IM_ASSERT(g.WithinEndChild == false); IM_ASSERT(g.WithinEndChild == false);
@ -9057,36 +9077,11 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im
void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags) void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != ImGuiNavLayer_Main)
return;
IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
ImRect bb_rel = window->NavRectRel[0];
ImGuiDir clip_dir = g.NavMoveDir; // Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) // popup is assembled and in case of appended popups it is not clear which EndPopup() call is final.
{ g.NavWrapRequestWindow = window;
bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x; g.NavWrapRequestFlags = move_flags;
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
{
bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
{
bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y;
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
{
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
} }
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). // FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
@ -9221,6 +9216,8 @@ static void ImGui::NavUpdate()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.IO.WantSetMousePos = false; g.IO.WantSetMousePos = false;
g.NavWrapRequestWindow = NULL;
g.NavWrapRequestFlags = ImGuiNavMoveFlags_None;
#if 0 #if 0
if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
#endif #endif
@ -9634,6 +9631,68 @@ static float ImGui::NavUpdatePageUpPageDown()
return 0.0f; return 0.0f;
} }
static void ImGui::NavEndFrame()
{
ImGuiContext& g = *GImGui;
// Show CTRL+TAB list window
if (g.NavWindowingTarget != NULL)
NavUpdateWindowingOverlay();
// Perform wrap-around in menus
ImGuiWindow* window = g.NavWrapRequestWindow;
ImGuiNavMoveFlags move_flags = g.NavWrapRequestFlags;
if (window != NULL && g.NavWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == ImGuiNavLayer_Main)
{
IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
ImRect bb_rel = window->NavRectRel[0];
ImGuiDir clip_dir = g.NavMoveDir;
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
{
bb_rel.Min.x = bb_rel.Max.x =
ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x;
if (move_flags & ImGuiNavMoveFlags_WrapX)
{
bb_rel.TranslateY(-bb_rel.GetHeight());
clip_dir = ImGuiDir_Up;
}
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
{
bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
if (move_flags & ImGuiNavMoveFlags_WrapX)
{
bb_rel.TranslateY(+bb_rel.GetHeight());
clip_dir = ImGuiDir_Down;
}
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
{
bb_rel.Min.y = bb_rel.Max.y =
ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y;
if (move_flags & ImGuiNavMoveFlags_WrapY)
{
bb_rel.TranslateX(-bb_rel.GetWidth());
clip_dir = ImGuiDir_Left;
}
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
{
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
if (move_flags & ImGuiNavMoveFlags_WrapY)
{
bb_rel.TranslateX(+bb_rel.GetWidth());
clip_dir = ImGuiDir_Right;
}
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
}
}
}
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N) static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -9841,8 +9900,8 @@ void ImGui::NavUpdateWindowingOverlay()
if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
return; return;
if (g.NavWindowingList == NULL) if (g.NavWindowingListWindow == NULL)
g.NavWindowingList = FindWindowByName("###NavWindowingList"); g.NavWindowingListWindow = FindWindowByName("###NavWindowingList");
ImGuiViewportP* viewport = /*g.NavWindow ? g.NavWindow->Viewport :*/ (ImGuiViewportP*)GetMainViewport(); ImGuiViewportP* viewport = /*g.NavWindow ? g.NavWindow->Viewport :*/ (ImGuiViewportP*)GetMainViewport();
SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
SetNextWindowPos(viewport->Pos + viewport->Size * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); SetNextWindowPos(viewport->Pos + viewport->Size * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
@ -10614,24 +10673,11 @@ static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandl
g.SettingsWindows.clear(); g.SettingsWindows.clear();
} }
// Apply to existing windows (if any)
static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{
ImGuiContext& g = *ctx;
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
if (settings->WantApply)
{
if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
ApplyWindowSettings(window, settings);
settings->WantApply = false;
}
}
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
{ {
ImGuiWindowSettings* settings = ImGui::FindOrCreateWindowSettings(name); ImGuiWindowSettings* settings = ImGui::FindOrCreateWindowSettings(name);
ImGuiID id = settings->ID; ImGuiID id = settings->ID;
*settings = ImGuiWindowSettings(); *settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry
settings->ID = id; settings->ID = id;
settings->WantApply = true; settings->WantApply = true;
return (void*)settings; return (void*)settings;
@ -10653,6 +10699,19 @@ static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
else if (sscanf(line, "ClassId=0x%X", &u1) == 1) { settings->ClassId = u1; } else if (sscanf(line, "ClassId=0x%X", &u1) == 1) { settings->ClassId = u1; }
} }
// Apply to existing windows (if any)
static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{
ImGuiContext& g = *ctx;
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
if (settings->WantApply)
{
if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
ApplyWindowSettings(window, settings);
settings->WantApply = false;
}
}
static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
{ {
// Gather data from windows that were active during this session // Gather data from windows that were active during this session
@ -11621,15 +11680,6 @@ struct ImGuiDockNodeSettings
ImGuiDockNodeSettings() { ID = ParentNodeId = ParentWindowId = SelectedWindowId = 0; SplitAxis = ImGuiAxis_None; Depth = 0; Flags = ImGuiDockNodeFlags_None; } ImGuiDockNodeSettings() { ID = ParentNodeId = ParentWindowId = SelectedWindowId = 0; SplitAxis = ImGuiAxis_None; Depth = 0; Flags = ImGuiDockNodeFlags_None; }
}; };
struct ImGuiDockContext
{
ImGuiStorage Nodes; // Map ID -> ImGuiDockNode*: Active nodes
ImVector<ImGuiDockRequest> Requests;
ImVector<ImGuiDockNodeSettings> SettingsNodes;
bool WantFullRebuild;
ImGuiDockContext() { WantFullRebuild = false; }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Docking: Forward Declarations // Docking: Forward Declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -11646,7 +11696,6 @@ namespace ImGui
static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx); static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx);
static ImGuiDockNode* DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id); static ImGuiDockNode* DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id);
static ImGuiDockNode* DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window); static ImGuiDockNode* DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window);
static void DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear_persistent_docking_refs); // Use root_id==0 to clear all
static void DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count); static void DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count);
static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id); // Use root_id==0 to add all static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id); // Use root_id==0 to add all
@ -11674,7 +11723,6 @@ namespace ImGui
static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired); static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
static bool DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir dir, ImRect& out_draw, bool outer_docking, ImVec2* test_mouse_pos); static bool DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir dir, ImRect& out_draw, bool outer_docking, ImVec2* test_mouse_pos);
static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node, char* buf, int buf_size) { ImFormatString(buf, buf_size, "##DockNode_%02X", node->ID); return buf; } static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node, char* buf, int buf_size) { ImFormatString(buf, buf_size, "##DockNode_%02X", node->ID); return buf; }
static int DockNodeGetDepth(const ImGuiDockNode* node) { int depth = 0; while (node->ParentNode) { node = node->ParentNode; depth++; } return depth; }
static int DockNodeGetTabOrder(ImGuiWindow* window); static int DockNodeGetTabOrder(ImGuiWindow* window);
// ImGuiDockNode tree manipulations // ImGuiDockNode tree manipulations
@ -11726,8 +11774,6 @@ namespace ImGui
void ImGui::DockContextInitialize(ImGuiContext* ctx) void ImGui::DockContextInitialize(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
IM_ASSERT(g.DockContext == NULL);
g.DockContext = IM_NEW(ImGuiDockContext)();
// Add .ini handle for persistent docking data // Add .ini handle for persistent docking data
ImGuiSettingsHandler ini_handler; ImGuiSettingsHandler ini_handler;
@ -11744,20 +11790,17 @@ void ImGui::DockContextInitialize(ImGuiContext* ctx)
void ImGui::DockContextShutdown(ImGuiContext* ctx) void ImGui::DockContextShutdown(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiDockContext* dc = &ctx->DockContext;
ImGuiDockContext* dc = ctx->DockContext;
for (int n = 0; n < dc->Nodes.Data.Size; n++) for (int n = 0; n < dc->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p) if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
IM_DELETE(node); IM_DELETE(node);
IM_DELETE(g.DockContext);
g.DockContext = NULL;
} }
void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear_persistent_docking_references) void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear_settings_refs)
{ {
IM_UNUSED(ctx); IM_UNUSED(ctx);
IM_ASSERT(ctx == GImGui); IM_ASSERT(ctx == GImGui);
DockBuilderRemoveNodeDockedWindows(root_id, clear_persistent_docking_references); DockBuilderRemoveNodeDockedWindows(root_id, clear_settings_refs);
DockBuilderRemoveNodeChildNodes(root_id); DockBuilderRemoveNodeChildNodes(root_id);
} }
@ -11766,11 +11809,11 @@ void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear
void ImGui::DockContextRebuildNodes(ImGuiContext* ctx) void ImGui::DockContextRebuildNodes(ImGuiContext* ctx)
{ {
IMGUI_DEBUG_LOG_DOCKING("DockContextRebuild()\n"); IMGUI_DEBUG_LOG_DOCKING("DockContextRebuild()\n");
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
SaveIniSettingsToMemory(); SaveIniSettingsToMemory();
ImGuiID root_id = 0; // Rebuild all ImGuiID root_id = 0; // Rebuild all
DockContextClearNodes(ctx, root_id, false); DockContextClearNodes(ctx, root_id, false);
DockContextBuildNodesFromSettings(ctx, dc->SettingsNodes.Data, dc->SettingsNodes.Size); DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
DockContextBuildAddWindowsToNodes(ctx, root_id); DockContextBuildAddWindowsToNodes(ctx, root_id);
} }
@ -11778,7 +11821,7 @@ void ImGui::DockContextRebuildNodes(ImGuiContext* ctx)
void ImGui::DockContextUpdateUndocking(ImGuiContext* ctx) void ImGui::DockContextUpdateUndocking(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
{ {
if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0) if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0)
@ -11822,7 +11865,7 @@ void ImGui::DockContextUpdateUndocking(ImGuiContext* ctx)
void ImGui::DockContextUpdateDocking(ImGuiContext* ctx) void ImGui::DockContextUpdateDocking(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
return; return;
@ -11842,7 +11885,7 @@ void ImGui::DockContextUpdateDocking(ImGuiContext* ctx)
static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id) static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id)
{ {
return (ImGuiDockNode*)ctx->DockContext->Nodes.GetVoidPtr(id); return (ImGuiDockNode*)ctx->DockContext.Nodes.GetVoidPtr(id);
} }
ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx) ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx)
@ -11866,14 +11909,14 @@ static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID id)
// We don't set node->LastFrameAlive on construction. Nodes are always created at all time to reflect .ini settings! // We don't set node->LastFrameAlive on construction. Nodes are always created at all time to reflect .ini settings!
IMGUI_DEBUG_LOG_DOCKING("DockContextAddNode 0x%08X\n", id); IMGUI_DEBUG_LOG_DOCKING("DockContextAddNode 0x%08X\n", id);
ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(id); ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(id);
ctx->DockContext->Nodes.SetVoidPtr(node->ID, node); ctx->DockContext.Nodes.SetVoidPtr(node->ID, node);
return node; return node;
} }
static void ImGui::DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node, bool merge_sibling_into_parent_node) static void ImGui::DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node, bool merge_sibling_into_parent_node)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
IMGUI_DEBUG_LOG_DOCKING("DockContextRemoveNode 0x%08X\n", node->ID); IMGUI_DEBUG_LOG_DOCKING("DockContextRemoveNode 0x%08X\n", node->ID);
IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node); IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node);
@ -11920,16 +11963,16 @@ struct ImGuiDockContextPruneNodeData
static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx) static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
IM_ASSERT(g.Windows.Size == 0); IM_ASSERT(g.Windows.Size == 0);
ImPool<ImGuiDockContextPruneNodeData> pool; ImPool<ImGuiDockContextPruneNodeData> pool;
pool.Reserve(dc->SettingsNodes.Size); pool.Reserve(dc->NodesSettings.Size);
// Count child nodes and compute RootID // Count child nodes and compute RootID
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++) for (int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
{ {
ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n]; ImGuiDockNodeSettings* settings = &dc->NodesSettings[settings_n];
ImGuiDockContextPruneNodeData* parent_data = settings->ParentNodeId ? pool.GetByKey(settings->ParentNodeId) : 0; ImGuiDockContextPruneNodeData* parent_data = settings->ParentNodeId ? pool.GetByKey(settings->ParentNodeId) : 0;
pool.GetOrAddByKey(settings->ID)->RootId = parent_data ? parent_data->RootId : settings->ID; pool.GetOrAddByKey(settings->ID)->RootId = parent_data ? parent_data->RootId : settings->ID;
if (settings->ParentNodeId) if (settings->ParentNodeId)
@ -11938,9 +11981,9 @@ static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
// Count reference to dock ids from dockspaces // Count reference to dock ids from dockspaces
// We track the 'auto-DockNode <- manual-Window <- manual-DockSpace' in order to avoid 'auto-DockNode' being ditched by DockContextPruneUnusedSettingsNodes() // We track the 'auto-DockNode <- manual-Window <- manual-DockSpace' in order to avoid 'auto-DockNode' being ditched by DockContextPruneUnusedSettingsNodes()
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++) for (int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
{ {
ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n]; ImGuiDockNodeSettings* settings = &dc->NodesSettings[settings_n];
if (settings->ParentWindowId != 0) if (settings->ParentWindowId != 0)
if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->ParentWindowId)) if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->ParentWindowId))
if (window_settings->DockId) if (window_settings->DockId)
@ -11960,9 +12003,9 @@ static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
} }
// Prune // Prune
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++) for (int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
{ {
ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n]; ImGuiDockNodeSettings* settings = &dc->NodesSettings[settings_n];
ImGuiDockContextPruneNodeData* data = pool.GetByKey(settings->ID); ImGuiDockContextPruneNodeData* data = pool.GetByKey(settings->ID);
if (data->CountWindows > 1) if (data->CountWindows > 1)
continue; continue;
@ -12054,7 +12097,7 @@ void ImGui::DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDo
req.DockSplitDir = split_dir; req.DockSplitDir = split_dir;
req.DockSplitRatio = split_ratio; req.DockSplitRatio = split_ratio;
req.DockSplitOuter = split_outer; req.DockSplitOuter = split_outer;
ctx->DockContext->Requests.push_back(req); ctx->DockContext.Requests.push_back(req);
} }
void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window) void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window)
@ -12062,7 +12105,7 @@ void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window)
ImGuiDockRequest req; ImGuiDockRequest req;
req.Type = ImGuiDockRequestType_Undock; req.Type = ImGuiDockRequestType_Undock;
req.UndockTargetWindow = window; req.UndockTargetWindow = window;
ctx->DockContext->Requests.push_back(req); ctx->DockContext.Requests.push_back(req);
} }
void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node) void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
@ -12070,12 +12113,12 @@ void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
ImGuiDockRequest req; ImGuiDockRequest req;
req.Type = ImGuiDockRequestType_Undock; req.Type = ImGuiDockRequestType_Undock;
req.UndockTargetNode = node; req.UndockTargetNode = node;
ctx->DockContext->Requests.push_back(req); ctx->DockContext.Requests.push_back(req);
} }
void ImGui::DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node) void ImGui::DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node)
{ {
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
for (int n = 0; n < dc->Requests.Size; n++) for (int n = 0; n < dc->Requests.Size; n++)
if (dc->Requests[n].DockTargetNode == node) if (dc->Requests[n].DockTargetNode == node)
dc->Requests[n].Type = ImGuiDockRequestType_None; dc->Requests[n].Type = ImGuiDockRequestType_None;
@ -13720,12 +13763,12 @@ void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG
if (child_0) if (child_0)
{ {
ctx->DockContext->Nodes.SetVoidPtr(child_0->ID, NULL); ctx->DockContext.Nodes.SetVoidPtr(child_0->ID, NULL);
IM_DELETE(child_0); IM_DELETE(child_0);
} }
if (child_1) if (child_1)
{ {
ctx->DockContext->Nodes.SetVoidPtr(child_1->ID, NULL); ctx->DockContext.Nodes.SetVoidPtr(child_1->ID, NULL);
IM_DELETE(child_1); IM_DELETE(child_1);
} }
} }
@ -14259,7 +14302,7 @@ void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id) void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
{ {
ImGuiContext* ctx = GImGui; ImGuiContext* ctx = GImGui;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
ImGuiDockNode* root_node = root_id ? DockContextFindNodeByID(ctx, root_id) : NULL; ImGuiDockNode* root_node = root_id ? DockContextFindNodeByID(ctx, root_id) : NULL;
if (root_id && root_node == NULL) if (root_id && root_node == NULL)
@ -14323,12 +14366,12 @@ void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
} }
} }
void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id, bool clear_persistent_docking_references) void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id, bool clear_settings_refs)
{ {
// Clear references in settings // Clear references in settings
ImGuiContext* ctx = GImGui; ImGuiContext* ctx = GImGui;
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
if (clear_persistent_docking_references) if (clear_settings_refs)
{ {
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
{ {
@ -14351,8 +14394,8 @@ void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id, bool clear_persi
{ {
const ImGuiID backup_dock_id = window->DockId; const ImGuiID backup_dock_id = window->DockId;
IM_UNUSED(backup_dock_id); IM_UNUSED(backup_dock_id);
DockContextProcessUndockWindow(ctx, window, clear_persistent_docking_references); DockContextProcessUndockWindow(ctx, window, clear_settings_refs);
if (!clear_persistent_docking_references) if (!clear_settings_refs)
IM_ASSERT(window->DockId == backup_dock_id); IM_ASSERT(window->DockId == backup_dock_id);
} }
} }
@ -14870,29 +14913,29 @@ static void ImGui::DockSettingsRemoveNodeReferences(ImGuiID* node_ids, int node_
static ImGuiDockNodeSettings* ImGui::DockSettingsFindNodeSettings(ImGuiContext* ctx, ImGuiID id) static ImGuiDockNodeSettings* ImGui::DockSettingsFindNodeSettings(ImGuiContext* ctx, ImGuiID id)
{ {
// FIXME-OPT // FIXME-OPT
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
for (int n = 0; n < dc->SettingsNodes.Size; n++) for (int n = 0; n < dc->NodesSettings.Size; n++)
if (dc->SettingsNodes[n].ID == id) if (dc->NodesSettings[n].ID == id)
return &dc->SettingsNodes[n]; return &dc->NodesSettings[n];
return NULL; return NULL;
} }
// Clear settings data // Clear settings data
static void ImGui::DockSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void ImGui::DockSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
dc->SettingsNodes.clear(); dc->NodesSettings.clear();
DockContextClearNodes(ctx, 0, true); DockContextClearNodes(ctx, 0, true);
} }
// Recreate dones based on settings data // Recreate nodes based on settings data
static void ImGui::DockSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void ImGui::DockSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
// Prune settings at boot time only // Prune settings at boot time only
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = &ctx->DockContext;
if (ctx->Windows.Size == 0) if (ctx->Windows.Size == 0)
DockContextPruneUnusedSettingsNodes(ctx); DockContextPruneUnusedSettingsNodes(ctx);
DockContextBuildNodesFromSettings(ctx, dc->SettingsNodes.Data, dc->SettingsNodes.Size); DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
DockContextBuildAddWindowsToNodes(ctx, 0); DockContextBuildAddWindowsToNodes(ctx, 0);
} }
@ -14938,11 +14981,10 @@ static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettings
if (sscanf(line, " NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; } if (sscanf(line, " NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
if (sscanf(line, " NoCloseButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoCloseButton; } if (sscanf(line, " NoCloseButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoCloseButton; }
if (sscanf(line, " Selected=0x%08X%n", &node.SelectedWindowId,&r) == 1) { line += r; } if (sscanf(line, " Selected=0x%08X%n", &node.SelectedWindowId,&r) == 1) { line += r; }
ImGuiDockContext* dc = ctx->DockContext;
if (node.ParentNodeId != 0) if (node.ParentNodeId != 0)
if (ImGuiDockNodeSettings* parent_settings = DockSettingsFindNodeSettings(ctx, node.ParentNodeId)) if (ImGuiDockNodeSettings* parent_settings = DockSettingsFindNodeSettings(ctx, node.ParentNodeId))
node.Depth = parent_settings->Depth + 1; node.Depth = parent_settings->Depth + 1;
dc->SettingsNodes.push_back(node); ctx->DockContext.NodesSettings.push_back(node);
} }
static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDockNode* node, int depth) static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDockNode* node, int depth)
@ -14959,7 +15001,7 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
node_settings.Pos = ImVec2ih(node->Pos); node_settings.Pos = ImVec2ih(node->Pos);
node_settings.Size = ImVec2ih(node->Size); node_settings.Size = ImVec2ih(node->Size);
node_settings.SizeRef = ImVec2ih(node->SizeRef); node_settings.SizeRef = ImVec2ih(node->SizeRef);
dc->SettingsNodes.push_back(node_settings); dc->NodesSettings.push_back(node_settings);
if (node->ChildNodes[0]) if (node->ChildNodes[0])
DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1); DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1);
if (node->ChildNodes[1]) if (node->ChildNodes[1])
@ -14969,29 +15011,29 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = g.DockContext; ImGuiDockContext* dc = &ctx->DockContext;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
return; return;
// Gather settings data // Gather settings data
// (unlike our windows settings, because nodes are always built we can do a full rewrite of the SettingsNode buffer) // (unlike our windows settings, because nodes are always built we can do a full rewrite of the SettingsNode buffer)
dc->SettingsNodes.resize(0); dc->NodesSettings.resize(0);
dc->SettingsNodes.reserve(dc->Nodes.Data.Size); dc->NodesSettings.reserve(dc->Nodes.Data.Size);
for (int n = 0; n < dc->Nodes.Data.Size; n++) for (int n = 0; n < dc->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p) if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
if (node->IsRootNode()) if (node->IsRootNode())
DockSettingsHandler_DockNodeToSettings(dc, node, 0); DockSettingsHandler_DockNodeToSettings(dc, node, 0);
int max_depth = 0; int max_depth = 0;
for (int node_n = 0; node_n < dc->SettingsNodes.Size; node_n++) for (int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
max_depth = ImMax((int)dc->SettingsNodes[node_n].Depth, max_depth); max_depth = ImMax((int)dc->NodesSettings[node_n].Depth, max_depth);
// Write to text buffer // Write to text buffer
buf->appendf("[%s][Data]\n", handler->TypeName); buf->appendf("[%s][Data]\n", handler->TypeName);
for (int node_n = 0; node_n < dc->SettingsNodes.Size; node_n++) for (int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
{ {
const int line_start_pos = buf->size(); (void)line_start_pos; const int line_start_pos = buf->size(); (void)line_start_pos;
const ImGuiDockNodeSettings* node_settings = &dc->SettingsNodes[node_n]; const ImGuiDockNodeSettings* node_settings = &dc->NodesSettings[node_n];
buf->appendf("%*s%s%*s", node_settings->Depth * 2, "", (node_settings->Flags & ImGuiDockNodeFlags_DockSpace) ? "DockSpace" : "DockNode ", (max_depth - node_settings->Depth) * 2, ""); // Text align nodes to facilitate looking at .ini file buf->appendf("%*s%s%*s", node_settings->Depth * 2, "", (node_settings->Flags & ImGuiDockNodeFlags_DockSpace) ? "DockSpace" : "DockNode ", (max_depth - node_settings->Depth) * 2, ""); // Text align nodes to facilitate looking at .ini file
buf->appendf(" ID=0x%08X", node_settings->ID); buf->appendf(" ID=0x%08X", node_settings->ID);
if (node_settings->ParentNodeId) if (node_settings->ParentNodeId)
@ -15266,8 +15308,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// Debugging enums // Debugging enums
enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type
const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" };
enum { TRT_OuterRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersDesired, TRT_ColumnsContentRowsFrozen, TRT_ColumnsContentRowsUnfrozen, TRT_Count }; // Tables Rect Type enum { TRT_OuterRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentRowsFrozen, TRT_ColumnsContentRowsUnfrozen, TRT_Count }; // Tables Rect Type
const char* trt_rects_names[TRT_Count] = { "OuterRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersDesired", "ColumnsContentRowsFrozen", "ColumnsContentRowsUnfrozen" }; const char* trt_rects_names[TRT_Count] = { "OuterRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentRowsFrozen", "ColumnsContentRowsUnfrozen" };
// State // State
static bool show_windows_rects = false; static bool show_windows_rects = false;
@ -15313,10 +15355,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return ImRect(); return ImRect();
} }
static void NodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, int elem_offset, bool show_mesh, bool show_aabb) static void NodeDrawCmdShowMeshAndBoundingBox(ImDrawList* fg_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, int elem_offset, bool show_mesh, bool show_aabb)
{ {
IM_ASSERT(show_mesh || show_aabb); IM_ASSERT(show_mesh || show_aabb);
ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
// Draw wire-frame version of all triangles // Draw wire-frame version of all triangles
@ -15345,6 +15386,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
fg_draw_list->Flags = backup_flags; fg_draw_list->Flags = backup_flags;
} }
// Note that both 'window' and 'viewport' may be NULL here. Viewport is generally null of destroyed popups which previously owned a viewport.
static void NodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, ImDrawList* draw_list, const char* label) static void NodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, ImDrawList* draw_list, const char* label)
{ {
bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);
@ -15383,7 +15425,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list) if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list)
NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, show_drawcmd_mesh, show_drawcmd_aabb); NodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, elem_offset, show_drawcmd_mesh, show_drawcmd_aabb);
if (!pcmd_node_open) if (!pcmd_node_open)
continue; continue;
@ -15402,7 +15444,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
ImGui::Selectable(buf); ImGui::Selectable(buf);
if (ImGui::IsItemHovered() && fg_draw_list) if (ImGui::IsItemHovered() && fg_draw_list)
NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, true, false); NodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, elem_offset, true, false);
// Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
@ -15622,7 +15664,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
}; };
// Tools // Tools
if (ImGui::TreeNode("Tools")) if (ImGui::TreeNode("Tools"))
{ {
@ -15711,13 +15752,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Funcs::NodeTable(g.Tables.GetByIndex(n)); Funcs::NodeTable(g.Tables.GetByIndex(n));
ImGui::TreePop(); ImGui::TreePop();
} }
#endif // #define IMGUI_HAS_TABLE #endif // #ifdef IMGUI_HAS_TABLE
// Details for Docking // Details for Docking
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
if (ImGui::TreeNode("Dock nodes")) if (ImGui::TreeNode("Dock nodes"))
{ {
ImGuiDockContext* dc = g.DockContext; ImGuiDockContext* dc = &g.DockContext;
ImGui::Checkbox("Ctrl shows window dock info", &show_docking_nodes); ImGui::Checkbox("Ctrl shows window dock info", &show_docking_nodes);
if (ImGui::SmallButton("Clear nodes")) { DockContextClearNodes(&g, 0, true); } if (ImGui::SmallButton("Clear nodes")) { DockContextClearNodes(&g, 0, true); }
ImGui::SameLine(); ImGui::SameLine();
@ -15728,7 +15769,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Funcs::NodeDockNode(node, "Node"); Funcs::NodeDockNode(node, "Node");
ImGui::TreePop(); ImGui::TreePop();
} }
#endif // #define IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK
// Settings // Settings
if (ImGui::TreeNode("Settings")) if (ImGui::TreeNode("Settings"))
@ -15759,6 +15800,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Funcs::NodeWindowSettings(settings); Funcs::NodeWindowSettings(settings);
ImGui::TreePop(); ImGui::TreePop();
} }
#ifdef IMGUI_HAS_TABLE #ifdef IMGUI_HAS_TABLE
if (ImGui::TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) if (ImGui::TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
{ {
@ -15766,17 +15808,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Funcs::NodeTableSettings(settings); Funcs::NodeTableSettings(settings);
ImGui::TreePop(); ImGui::TreePop();
} }
#endif #endif // #ifdef IMGUI_HAS_TABLE
#ifdef IMGUI_HAS_DOCK
if (ImGui::TreeNode("SettingsDocking", "Settings packed data: Docking")) if (ImGui::TreeNode("SettingsDocking", "Settings packed data: Docking"))
{ {
ImGuiDockContext* dc = &g.DockContext;
ImGui::Text("In SettingsWindows:"); ImGui::Text("In SettingsWindows:");
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
if (settings->DockId != 0) if (settings->DockId != 0)
ImGui::BulletText("Window '%s' -> DockId %08X", settings->GetName(), settings->DockId); ImGui::BulletText("Window '%s' -> DockId %08X", settings->GetName(), settings->DockId);
ImGui::Text("In SettingsNodes:"); ImGui::Text("In SettingsNodes:");
for (int n = 0; n < g.DockContext->SettingsNodes.Size; n++) for (int n = 0; n < dc->NodesSettings.Size; n++)
{ {
ImGuiDockNodeSettings* settings = &g.DockContext->SettingsNodes[n]; ImGuiDockNodeSettings* settings = &dc->NodesSettings[n];
const char* selected_tab_name = NULL; const char* selected_tab_name = NULL;
if (settings->SelectedWindowId) if (settings->SelectedWindowId)
{ {
@ -15789,6 +15834,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
ImGui::TreePop(); ImGui::TreePop();
} }
#endif // #ifdef IMGUI_HAS_DOCK
if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size()))
{ {
char* buf = (char*)(void*)(g.SettingsIniData.Buf.Data ? g.SettingsIniData.Buf.Data : ""); char* buf = (char*)(void*)(g.SettingsIniData.Buf.Data ? g.SettingsIniData.Buf.Data : "");
@ -15855,14 +15902,15 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGuiTable* table = g.Tables.GetByIndex(table_n); ImGuiTable* table = g.Tables.GetByIndex(table_n);
} }
} }
#endif // #define IMGUI_HAS_TABLE #endif // #ifdef IMGUI_HAS_TABLE
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
// Overlay: Display Docking info // Overlay: Display Docking info
if (show_docking_nodes && g.IO.KeyCtrl) if (show_docking_nodes && g.IO.KeyCtrl)
{ {
for (int n = 0; n < g.DockContext->Nodes.Data.Size; n++) ImGuiDockContext* dc = &g.DockContext;
if (ImGuiDockNode* node = (ImGuiDockNode*)g.DockContext->Nodes.Data[n].val_p) for (int n = 0; n < dc->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
{ {
ImGuiDockNode* root_node = DockNodeGetRootNode(node); ImGuiDockNode* root_node = DockNodeGetRootNode(node);
if (ImGuiDockNode* hovered_node = DockNodeTreeFindNodeByPos(root_node, g.IO.MousePos)) if (ImGuiDockNode* hovered_node = DockNodeTreeFindNodeByPos(root_node, g.IO.MousePos))
@ -15882,7 +15930,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf); overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf);
} }
} }
#endif // #define IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK
ImGui::End(); ImGui::End();
} }

View File

@ -1570,7 +1570,7 @@ struct ImGuiIO
//------------------------------------------------------------------ //------------------------------------------------------------------
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends. float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends.
ImGuiID MouseHoveredViewport; // (Optional) When using multiple viewports: viewport the OS mouse cursor is hovering _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag, and _REGARDLESS_ of whether another viewport is focused. Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows). ImGuiID MouseHoveredViewport; // (Optional) When using multiple viewports: viewport the OS mouse cursor is hovering _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag, and _REGARDLESS_ of whether another viewport is focused. Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows).

View File

@ -633,13 +633,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
if (points_count < 2) if (points_count < 2)
return; return;
const ImVec2 uv = _Data->TexUvWhitePixel; const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
int count = points_count; int count = points_count;
if (!closed) if (!closed)
count = points_count-1; count = points_count-1;
const bool thick_line = thickness > 1.0f; const bool thick_line = (thickness > 1.0f);
if (Flags & ImDrawListFlags_AntiAliasedLines) if (Flags & ImDrawListFlags_AntiAliasedLines)
{ {
// Anti-aliased stroke // Anti-aliased stroke
@ -710,9 +709,9 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// Add vertices // Add vertices
for (int i = 0; i < points_count; i++) for (int i = 0; i < points_count; i++)
{ {
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;
_VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; _VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans;
_VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans; _VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans;
_VtxWritePtr += 3; _VtxWritePtr += 3;
} }
} }
@ -721,22 +720,23 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
if (!closed) if (!closed)
{ {
const int points_last = points_count - 1;
temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE); temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);
temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness); temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);
temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness); temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);
temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE); temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);
temp_points[(points_count-1)*4+0] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE); temp_points[points_last * 4 + 0] = points[points_last] + temp_normals[points_last] * (half_inner_thickness + AA_SIZE);
temp_points[(points_count-1)*4+1] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness); temp_points[points_last * 4 + 1] = points[points_last] + temp_normals[points_last] * (half_inner_thickness);
temp_points[(points_count-1)*4+2] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness); temp_points[points_last * 4 + 2] = points[points_last] - temp_normals[points_last] * (half_inner_thickness);
temp_points[(points_count-1)*4+3] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE); temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE);
} }
// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
unsigned int idx1 = _VtxCurrentIdx; unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++) for (int i1 = 0; i1 < count; i1++)
{ {
const int i2 = (i1+1) == points_count ? 0 : i1+1; const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment
unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4; const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment
// Average normals // Average normals
float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
@ -759,12 +759,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
out_vtx[3].y = points[i2].y - dm_out_y; out_vtx[3].y = points[i2].y - dm_out_y;
// Add indexes // Add indexes
_IdxWritePtr[0] = (ImDrawIdx)(idx2+1); _IdxWritePtr[1] = (ImDrawIdx)(idx1+1); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2); _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2);
_IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+1); _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1);
_IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0); _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0);
_IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10] = (ImDrawIdx)(idx2+0); _IdxWritePtr[11] = (ImDrawIdx)(idx2+1); _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1);
_IdxWritePtr[12] = (ImDrawIdx)(idx2+2); _IdxWritePtr[13] = (ImDrawIdx)(idx1+2); _IdxWritePtr[14] = (ImDrawIdx)(idx1+3); _IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3);
_IdxWritePtr[15] = (ImDrawIdx)(idx1+3); _IdxWritePtr[16] = (ImDrawIdx)(idx2+3); _IdxWritePtr[17] = (ImDrawIdx)(idx2+2); _IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3); _IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3); _IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2);
_IdxWritePtr += 18; _IdxWritePtr += 18;
idx1 = idx2; idx1 = idx2;
@ -773,10 +773,10 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// Add vertices // Add vertices
for (int i = 0; i < points_count; i++) for (int i = 0; i < points_count; i++)
{ {
_VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans; _VtxWritePtr[0].pos = temp_points[i * 4 + 0]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col_trans;
_VtxWritePtr[1].pos = temp_points[i*4+1]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; _VtxWritePtr[1].pos = temp_points[i * 4 + 1]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col;
_VtxWritePtr[2].pos = temp_points[i*4+2]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; _VtxWritePtr[2].pos = temp_points[i * 4 + 2]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col;
_VtxWritePtr[3].pos = temp_points[i*4+3]; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col_trans; _VtxWritePtr[3].pos = temp_points[i * 4 + 3]; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans;
_VtxWritePtr += 4; _VtxWritePtr += 4;
} }
} }
@ -801,14 +801,14 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
dx *= (thickness * 0.5f); dx *= (thickness * 0.5f);
dy *= (thickness * 0.5f); dy *= (thickness * 0.5f);
_VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;
_VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col;
_VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col;
_VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col;
_VtxWritePtr += 4; _VtxWritePtr += 4;
_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2);
_IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3);
_IdxWritePtr += 6; _IdxWritePtr += 6;
_VtxCurrentIdx += 4; _VtxCurrentIdx += 4;
} }
@ -2346,7 +2346,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
{ {
0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3131, 0x3163, // Korean alphabets 0x3131, 0x3163, // Korean alphabets
0xAC00, 0xD79D, // Korean characters 0xAC00, 0xD7A3, // Korean characters
0, 0,
}; };
return &ranges[0]; return &ranges[0];

File diff suppressed because it is too large Load Diff

View File

@ -2977,7 +2977,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
// Only mark as edited if new value is different // Only mark as edited if new value is different
value_changed = memcmp(&data_type, p_data, data_type_size) != 0; value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
} }
@ -7289,6 +7289,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
tab_bar->NextSelectedTabId = id; tab_bar->NextSelectedTabId = id;
hovered |= (g.HoveredId == id); hovered |= (g.HoveredId == id);
// Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow()
// will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id.
if (held && docked_window && g.ActiveId == id && g.ActiveIdIsJustActivated)
g.ActiveIdWindow = docked_window;
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
if (!held) if (!held)
SetItemAllowOverlap(); SetItemAllowOverlap();

View File

@ -74,7 +74,7 @@ enum GlfwClientApi
static GLFWwindow* g_Window = NULL; // Main window static GLFWwindow* g_Window = NULL; // Main window
static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
static double g_Time = 0.0; static double g_Time = 0.0;
static bool g_MouseJustPressed[5] = { false, false, false, false, false }; static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_InstalledCallbacks = false; static bool g_InstalledCallbacks = false;
static bool g_WantUpdateMonitors = true; static bool g_WantUpdateMonitors = true;

View File

@ -15,6 +15,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix. // 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset. // 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
// 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader. // 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
@ -191,6 +192,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
#elif defined(IMGUI_IMPL_OPENGL_ES3) #elif defined(IMGUI_IMPL_OPENGL_ES3)
if (glsl_version == NULL) if (glsl_version == NULL)
glsl_version = "#version 300 es"; glsl_version = "#version 300 es";
#elif defined(__APPLE__)
if (glsl_version == NULL)
glsl_version = "#version 150";
#else #else
if (glsl_version == NULL) if (glsl_version == NULL)
glsl_version = "#version 130"; glsl_version = "#version 130";