mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-13 00:09:55 +02:00
Merge branch 'master' into docking
# Conflicts: # examples/imgui_impl_opengl3.cpp # imgui.cpp # imgui_draw.cpp # imgui_internal.h
This commit is contained in:
262
imgui.cpp
262
imgui.cpp
@ -373,12 +373,12 @@ CODE
|
||||
|
||||
(Docking/Viewport Branch)
|
||||
- 2019/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
|
||||
- reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are probably not what you want anymore.
|
||||
- reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are probably not what you want anymore.
|
||||
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
|
||||
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
||||
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
||||
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
||||
- 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
|
||||
|
||||
|
||||
|
||||
- 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete).
|
||||
- 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete).
|
||||
@ -586,17 +586,17 @@ CODE
|
||||
Q: Where is the documentation?
|
||||
A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
|
||||
- Run the examples/ and explore them.
|
||||
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
||||
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
||||
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
|
||||
folder to explain how to integrate Dear ImGui with your own engine/application.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments
|
||||
associated to it.
|
||||
|
||||
Q: Which version should I get?
|
||||
A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
|
||||
and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
|
||||
A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
|
||||
and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
|
||||
fixed fast when reported. You may also peak at the 'docking' branch which includes:
|
||||
- Docking/Merging features (https://github.com/ocornut/imgui/issues/2109)
|
||||
- Multi-viewport features (https://github.com/ocornut/imgui/issues/1542)
|
||||
@ -608,11 +608,11 @@ CODE
|
||||
for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
|
||||
|
||||
Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"?
|
||||
A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
|
||||
when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
|
||||
(immediate-mode graphical user interface) was coined before and is being used in variety of other
|
||||
situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
|
||||
To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
|
||||
A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
|
||||
when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
|
||||
(immediate-mode graphical user interface) was coined before and is being used in variety of other
|
||||
situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
|
||||
To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
|
||||
longer name "Dear ImGui" that people can use to refer to this specific library.
|
||||
Please try to refer to this library as "Dear ImGui".
|
||||
|
||||
@ -1090,7 +1090,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2&
|
||||
// Navigation
|
||||
static void NavUpdate();
|
||||
static void NavUpdateWindowing();
|
||||
static void NavUpdateWindowingList();
|
||||
static void NavUpdateWindowingOverlay();
|
||||
static void NavUpdateMoveResult();
|
||||
static float NavUpdatePageUpPageDown(int allowed_dir_flags);
|
||||
static inline void NavUpdateAnyRequestFlag();
|
||||
@ -2532,14 +2532,18 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
|
||||
|
||||
// Another overly complex function until we reorganize everything into a nice all-in-one helper.
|
||||
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
|
||||
// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
|
||||
void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
|
||||
// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
|
||||
void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (text_end_full == NULL)
|
||||
text_end_full = FindRenderedTextEnd(text);
|
||||
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
|
||||
|
||||
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
|
||||
//draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255));
|
||||
//draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255));
|
||||
// FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
|
||||
if (text_size.x > pos_max.x - pos_min.x)
|
||||
{
|
||||
// Hello wo...
|
||||
@ -2547,15 +2551,33 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
||||
// min max ellipsis_max
|
||||
// <-> this is generally some padding value
|
||||
|
||||
// FIXME-STYLE: RenderPixelEllipsis() style should use actual font data.
|
||||
const ImFont* font = draw_list->_Data->Font;
|
||||
const float font_size = draw_list->_Data->FontSize;
|
||||
const int ellipsis_dot_count = 3;
|
||||
const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
|
||||
const char* text_end_ellipsis = NULL;
|
||||
|
||||
float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f);
|
||||
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
||||
ImWchar ellipsis_char = font->EllipsisChar;
|
||||
int ellipsis_char_count = 1;
|
||||
if (ellipsis_char == (ImWchar)-1)
|
||||
{
|
||||
ellipsis_char = (ImWchar)'.';
|
||||
ellipsis_char_count = 3;
|
||||
}
|
||||
const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
|
||||
|
||||
float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side
|
||||
float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis
|
||||
|
||||
if (ellipsis_char_count > 1)
|
||||
{
|
||||
// Full ellipsis size without free spacing after it.
|
||||
const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize);
|
||||
ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
|
||||
ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
|
||||
}
|
||||
|
||||
// We can now claim the space between pos_max.x and ellipsis_max.x
|
||||
const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
|
||||
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
||||
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
|
||||
{
|
||||
// Always display at least 1 character if there's no room for character + ellipsis
|
||||
@ -2564,15 +2586,20 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
||||
}
|
||||
while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
|
||||
{
|
||||
// Trim trailing space before ellipsis
|
||||
// Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
|
||||
text_end_ellipsis--;
|
||||
text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
|
||||
}
|
||||
RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
|
||||
|
||||
const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f;
|
||||
if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x)
|
||||
RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count);
|
||||
// Render text, render ellipsis
|
||||
RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
|
||||
float ellipsis_x = pos_min.x + text_size_clipped_x;
|
||||
if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
|
||||
for (int i = 0; i < ellipsis_char_count; i++)
|
||||
{
|
||||
font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
|
||||
ellipsis_x += ellipsis_glyph_width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3059,8 +3086,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
|
||||
{
|
||||
// Navigation processing runs prior to clipping early-out
|
||||
// (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
|
||||
// (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
|
||||
// unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
|
||||
// (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
|
||||
// unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
|
||||
// thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
|
||||
// We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able
|
||||
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
|
||||
@ -3505,7 +3532,7 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to merge the window back into the main viewport.
|
||||
// Try to merge the window back into the main viewport.
|
||||
// This works because MouseViewport should be != MovingWindow->Viewport on release (as per code in UpdateViewports)
|
||||
if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
|
||||
UpdateTryMergeWindowIntoHostViewport(moving_window, g.MouseViewport);
|
||||
@ -3830,7 +3857,7 @@ static void NewFrameSanityChecks()
|
||||
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
|
||||
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!");
|
||||
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
|
||||
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
||||
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
||||
for (int n = 0; n < ImGuiKey_COUNT; n++)
|
||||
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
|
||||
|
||||
@ -4291,7 +4318,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
// May trigger for you if you are using PrimXXX functions incorrectly.
|
||||
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
||||
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
||||
@ -4300,7 +4327,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
||||
|
||||
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
||||
// If this assert triggers because you are drawing lots of stuff manually:
|
||||
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
||||
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
||||
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
|
||||
// - If you want large meshes with more than 64K vertices, you can either:
|
||||
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
|
||||
@ -4309,9 +4336,9 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
||||
// (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
||||
// Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time:
|
||||
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes.
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes.
|
||||
// 2 and 4 bytes indices are generally supported by most graphics API.
|
||||
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
||||
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
||||
// the 64K limit to split your draw commands in multiple draw lists.
|
||||
if (sizeof(ImDrawIdx) == 2)
|
||||
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
||||
@ -4493,8 +4520,8 @@ void ImGui::EndFrame()
|
||||
EndFrameDrawDimmedBackgrounds();
|
||||
|
||||
// Show CTRL+TAB list window
|
||||
if (g.NavWindowingTarget)
|
||||
NavUpdateWindowingList();
|
||||
if (g.NavWindowingTarget != NULL)
|
||||
NavUpdateWindowingOverlay();
|
||||
|
||||
SetCurrentViewport(NULL, NULL);
|
||||
|
||||
@ -4560,7 +4587,7 @@ void ImGui::Render()
|
||||
EndFrame();
|
||||
g.FrameCountRendered = g.FrameCount;
|
||||
g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsRenderWindows = 0;
|
||||
|
||||
|
||||
// Add background ImDrawList (for each active viewport)
|
||||
for (int n = 0; n != g.Viewports.Size; n++)
|
||||
{
|
||||
@ -4683,7 +4710,7 @@ static void FindHoveredWindow()
|
||||
if (hole_bb.Contains(g.IO.MousePos - window->Pos))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (hovered_window == NULL)
|
||||
hovered_window = window;
|
||||
if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
|
||||
@ -4731,7 +4758,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key)
|
||||
// Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]!
|
||||
bool ImGui::IsKeyDown(int user_key_index)
|
||||
{
|
||||
if (user_key_index < 0)
|
||||
if (user_key_index < 0)
|
||||
return false;
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||
@ -4963,7 +4990,7 @@ bool ImGui::IsItemFocused()
|
||||
if (g.NavId == 0 || g.NavDisableHighlight || g.NavId != window->DC.LastItemId)
|
||||
return false;
|
||||
|
||||
// Special handling for the dummy item after Begin() which represent the title bar or tab.
|
||||
// Special handling for the dummy item after Begin() which represent the title bar or tab.
|
||||
// When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
|
||||
if (window->DC.LastItemId == window->ID && window->WriteAccessed)
|
||||
return false;
|
||||
@ -5650,7 +5677,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
}
|
||||
|
||||
// Title bar
|
||||
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
|
||||
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
|
||||
// in order for their pos/size to be matching their undocking state.)
|
||||
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
|
||||
{
|
||||
@ -5718,7 +5745,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
|
||||
ImGuiWindowFlags flags = window->Flags;
|
||||
|
||||
const bool has_close_button = (p_open != NULL);
|
||||
const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse);
|
||||
const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
|
||||
|
||||
// Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
|
||||
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
|
||||
@ -6195,7 +6222,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
|
||||
// For popups and menus that may be protruding out of their parent viewport, we enable _NoFocusOnClick so that clicking on them
|
||||
// won't steal the OS focus away from their parent window (which may be reflected in OS the title bar decoration).
|
||||
// Setting _NoFocusOnClick would technically prevent us from bringing back to front in case they are being covered by an OS window from a different app,
|
||||
// Setting _NoFocusOnClick would technically prevent us from bringing back to front in case they are being covered by an OS window from a different app,
|
||||
// but it shouldn't be much of a problem considering those are already popups that are closed when clicking elsewhere.
|
||||
if (is_short_lived_floating_window && (flags & ImGuiWindowFlags_Modal) == 0)
|
||||
viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
|
||||
@ -6321,7 +6348,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->OuterRectClipped.ClipWith(host_rect);
|
||||
|
||||
// Inner rectangle
|
||||
// Not affected by window border size. Used by:
|
||||
// Not affected by window border size. Used by:
|
||||
// - InnerClipRect
|
||||
// - ScrollToBringRectIntoView()
|
||||
// - NavUpdatePageUpPageDown()
|
||||
@ -6586,7 +6613,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
|
||||
// When we are about to select this tab (which will only be visible on the _next frame_), flag it with a non-zero HiddenFramesCannotSkipItems.
|
||||
// This will have the important effect of actually returning true in Begin() and not setting SkipItems, allowing an earlier submission of the window contents.
|
||||
// This is analogous to regular windows being hidden from one frame.
|
||||
// This is analogous to regular windows being hidden from one frame.
|
||||
// It is especially important as e.g. nested TabBars would otherwise generate flicker in the form of one empty frame, or focus requests won't be processed.
|
||||
if (window->DockIsActive && !window->DockTabIsVisible)
|
||||
{
|
||||
@ -6787,7 +6814,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
|
||||
if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow))
|
||||
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
||||
{
|
||||
// FIXME-DOCKING: This is failing (lagging by one frame) for docked windows.
|
||||
// FIXME-DOCKING: This is failing (lagging by one frame) for docked windows.
|
||||
// If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B.
|
||||
// We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update)
|
||||
// to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself?
|
||||
@ -7410,11 +7437,11 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi
|
||||
}
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
void ImGui::SetNextWindowPosCenter(ImGuiCond cond)
|
||||
{
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
SetNextWindowPos(viewport->Pos + viewport->Size * 0.5f, cond, ImVec2(0.5f, 0.5f));
|
||||
SetNextWindowViewport(viewport->ID);
|
||||
void ImGui::SetNextWindowPosCenter(ImGuiCond cond)
|
||||
{
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
SetNextWindowPos(viewport->Pos + viewport->Size * 0.5f, cond, ImVec2(0.5f, 0.5f));
|
||||
SetNextWindowViewport(viewport->ID);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -8818,7 +8845,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
|
||||
ImGui::NavMoveRequestCancel();
|
||||
NavMoveRequestCancel();
|
||||
g.NavMoveDir = move_dir;
|
||||
g.NavMoveClipDir = clip_dir;
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
||||
@ -9159,10 +9186,10 @@ static void ImGui::NavUpdate()
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
||||
if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||
{
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left;
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Right;
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up;
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down;
|
||||
if ((allowed_dir_flags & (1 << ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Left; }
|
||||
if ((allowed_dir_flags & (1 << ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Right; }
|
||||
if ((allowed_dir_flags & (1 << ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Up; }
|
||||
if ((allowed_dir_flags & (1 << ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Down; }
|
||||
}
|
||||
g.NavMoveClipDir = g.NavMoveDir;
|
||||
}
|
||||
@ -9175,7 +9202,8 @@ static void ImGui::NavUpdate()
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
|
||||
}
|
||||
|
||||
// Update PageUp/PageDown scroll
|
||||
// Update PageUp/PageDown/Home/End scroll
|
||||
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
||||
float nav_scoring_rect_offset_y = 0.0f;
|
||||
if (nav_keyboard_active)
|
||||
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
|
||||
@ -9294,8 +9322,18 @@ static void ImGui::NavUpdateMoveResult()
|
||||
// Scroll to keep newly navigated item fully into view.
|
||||
if (g.NavLayer == 0)
|
||||
{
|
||||
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
||||
ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
|
||||
ImVec2 delta_scroll;
|
||||
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge)
|
||||
{
|
||||
float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
|
||||
delta_scroll.y = result->Window->Scroll.y - scroll_target;
|
||||
SetScrollY(result->Window, scroll_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
||||
delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
|
||||
}
|
||||
|
||||
// Offset our result position so mouse position can be applied immediately after in NavUpdate()
|
||||
result->RectRel.TranslateX(-delta_scroll.x);
|
||||
@ -9314,6 +9352,7 @@ static void ImGui::NavUpdateMoveResult()
|
||||
g.NavMoveFromClampedRefRect = false;
|
||||
}
|
||||
|
||||
// Handle PageUp/PageDown/Home/End keys
|
||||
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -9323,9 +9362,11 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
||||
return 0.0f;
|
||||
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
||||
bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
||||
if (page_up_held != page_down_held) // If either (not both) are pressed
|
||||
const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
||||
const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
||||
const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
||||
const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
||||
if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed
|
||||
{
|
||||
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
|
||||
{
|
||||
@ -9334,26 +9375,49 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
||||
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
|
||||
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
||||
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
|
||||
else if (home_pressed)
|
||||
SetScrollY(window, 0.0f);
|
||||
else if (end_pressed)
|
||||
SetScrollY(window, window->ScrollMax.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
||||
ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
||||
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
||||
float nav_scoring_rect_offset_y = 0.0f;
|
||||
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
||||
{
|
||||
nav_scoring_rect_offset_y = -page_offset_y;
|
||||
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
||||
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
|
||||
g.NavMoveClipDir = ImGuiDir_Up;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||
}
|
||||
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
||||
{
|
||||
nav_scoring_rect_offset_y = +page_offset_y;
|
||||
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
||||
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
|
||||
g.NavMoveClipDir = ImGuiDir_Down;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||
}
|
||||
else if (home_pressed)
|
||||
{
|
||||
// FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
|
||||
// Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result.
|
||||
// Preserve current horizontal position if we have any.
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y;
|
||||
if (nav_rect_rel.IsInverted())
|
||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||
g.NavMoveDir = ImGuiDir_Down;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
||||
}
|
||||
else if (end_pressed)
|
||||
{
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y;
|
||||
if (nav_rect_rel.IsInverted())
|
||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||
g.NavMoveDir = ImGuiDir_Up;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
||||
}
|
||||
return nav_scoring_rect_offset_y;
|
||||
}
|
||||
}
|
||||
@ -9559,7 +9623,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
|
||||
}
|
||||
|
||||
// Overlay displayed when using CTRL+TAB. Called by EndFrame().
|
||||
void ImGui::NavUpdateWindowingList()
|
||||
void ImGui::NavUpdateWindowingOverlay()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.NavWindowingTarget != NULL);
|
||||
@ -10471,7 +10535,7 @@ void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& o
|
||||
// 1) We test if ImGuiConfigFlags_ViewportsEnable was just toggled, which allows us to conveniently
|
||||
// translate imgui windows from OS-window-local to absolute coordinates or vice-versa.
|
||||
// 2) If it's not going to fit into the new size, keep it at same absolute position.
|
||||
// One problem with this is that most Win32 applications doesn't update their render while dragging,
|
||||
// One problem with this is that most Win32 applications doesn't update their render while dragging,
|
||||
// and so the window will appear to teleport when releasing the mouse.
|
||||
const bool translate_all_windows = (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != (g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable);
|
||||
ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size);
|
||||
@ -10498,7 +10562,7 @@ void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale)
|
||||
}
|
||||
|
||||
// If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves.
|
||||
// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||
// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||
// B) It requires Platform_GetWindowFocus to be implemented by back-end.
|
||||
static ImGuiViewportP* FindHoveredViewportFromPlatformWindowStack(const ImVec2 mouse_platform_pos)
|
||||
{
|
||||
@ -10566,7 +10630,7 @@ static void ImGui::UpdateViewportsNewFrame()
|
||||
g.Windows[window_n]->Viewport = NULL;
|
||||
g.Windows[window_n]->ViewportOwned = false;
|
||||
}
|
||||
if (viewport == g.MouseLastHoveredViewport)
|
||||
if (viewport == g.MouseLastHoveredViewport)
|
||||
g.MouseLastHoveredViewport = NULL;
|
||||
g.Viewports.erase(g.Viewports.Data + n);
|
||||
|
||||
@ -10582,7 +10646,7 @@ static void ImGui::UpdateViewportsNewFrame()
|
||||
const bool platform_funcs_available = viewport->PlatformWindowCreated;
|
||||
if ((g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
|
||||
{
|
||||
// Update Position and Size (from Platform Window to ImGui) if requested.
|
||||
// Update Position and Size (from Platform Window to ImGui) if requested.
|
||||
// We do it early in the frame instead of waiting for UpdatePlatformWindows() to avoid a frame of lag when moving/resizing using OS facilities.
|
||||
if (!(viewport->Flags & ImGuiViewportFlags_Minimized) && platform_funcs_available)
|
||||
{
|
||||
@ -10652,7 +10716,7 @@ static void ImGui::UpdateViewportsNewFrame()
|
||||
else
|
||||
{
|
||||
// If the back-end doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
|
||||
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||
// B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
|
||||
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
|
||||
}
|
||||
@ -10664,11 +10728,11 @@ static void ImGui::UpdateViewportsNewFrame()
|
||||
// Update mouse reference viewport
|
||||
// (when moving a window we aim at its viewport, but this will be overwritten below if we go in drag and drop mode)
|
||||
if (g.MovingWindow)
|
||||
g.MouseViewport = g.MovingWindow->Viewport;
|
||||
g.MouseViewport = g.MovingWindow->Viewport;
|
||||
else
|
||||
g.MouseViewport = g.MouseLastHoveredViewport;
|
||||
|
||||
// When dragging something, always refer to the last hovered viewport.
|
||||
// When dragging something, always refer to the last hovered viewport.
|
||||
// - when releasing a moving window we will revert to aiming behind (at viewport_hovered)
|
||||
// - when we are between viewports, our dragged preview will tend to show in the last viewport _even_ if we don't have tooltips in their viewports (when lacking monitor info)
|
||||
// - consider the case of holding on a menu item to browse child menus: even thou a mouse button is held, there's no active id because menu items only react on mouse release.
|
||||
@ -10909,7 +10973,7 @@ void ImGui::UpdatePlatformWindows()
|
||||
{
|
||||
ImGuiViewportP* viewport = g.Viewports[i];
|
||||
|
||||
// Destroy platform window if the viewport hasn't been submitted or if it is hosting a hidden window
|
||||
// Destroy platform window if the viewport hasn't been submitted or if it is hosting a hidden window
|
||||
// (the implicit/fallback Debug##Default window will be registering its viewport then be disabled, causing a dummy DestroyPlatformWindow to be made each frame)
|
||||
bool destroy_platform_window = false;
|
||||
destroy_platform_window |= (viewport->LastFrameActive < g.FrameCount - 1);
|
||||
@ -10982,7 +11046,7 @@ void ImGui::UpdatePlatformWindows()
|
||||
// Show window
|
||||
g.PlatformIO.Platform_ShowWindow(viewport);
|
||||
|
||||
// Even without focus, we assume the window becomes front-most.
|
||||
// Even without focus, we assume the window becomes front-most.
|
||||
// This is useful for our platform z-order heuristic when io.MouseHoveredViewport is not available.
|
||||
if (viewport->LastFrontMostStampCount != g.ViewportFrontMostStampCount)
|
||||
viewport->LastFrontMostStampCount = ++g.ViewportFrontMostStampCount;
|
||||
@ -10993,7 +11057,7 @@ void ImGui::UpdatePlatformWindows()
|
||||
}
|
||||
|
||||
// Update our implicit z-order knowledge of platform windows, which is used when the back-end cannot provide io.MouseHoveredViewport.
|
||||
// When setting Platform_GetWindowFocus, it is expected that the platform back-end can handle calls without crashing if it doesn't have data stored.
|
||||
// When setting Platform_GetWindowFocus, it is expected that the platform back-end can handle calls without crashing if it doesn't have data stored.
|
||||
if (g.PlatformIO.Platform_GetWindowFocus != NULL)
|
||||
{
|
||||
ImGuiViewportP* focused_viewport = NULL;
|
||||
@ -11061,7 +11125,7 @@ static int ImGui::FindPlatformMonitorForPos(const ImVec2& pos)
|
||||
|
||||
// Search for the monitor with the largest intersection area with the given rectangle
|
||||
// We generally try to avoid searching loops but the monitor count should be very small here
|
||||
// FIXME-OPT: We could test the last monitor used for that viewport first, and early
|
||||
// FIXME-OPT: We could test the last monitor used for that viewport first, and early
|
||||
static int ImGui::FindPlatformMonitorForRect(const ImRect& rect)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -11070,7 +11134,7 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect)
|
||||
if (monitor_count <= 1)
|
||||
return monitor_count - 1;
|
||||
|
||||
// Use a minimum threshold of 1.0f so a zero-sized rect won't false positive, and will still find the correct monitor given its position.
|
||||
// Use a minimum threshold of 1.0f so a zero-sized rect won't false positive, and will still find the correct monitor given its position.
|
||||
// This is necessary for tooltips which always resize down to zero at first.
|
||||
const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f);
|
||||
int best_monitor_n = -1;
|
||||
@ -11121,12 +11185,12 @@ void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
|
||||
|
||||
void ImGui::DestroyPlatformWindows()
|
||||
{
|
||||
// We call the destroy window on every viewport (including the main viewport, index 0) to give a chance to the back-end
|
||||
// to clear any data they may have stored in e.g. PlatformUserData, RendererUserData.
|
||||
// It is convenient for the platform back-end code to store something in the main viewport, in order for e.g. the mouse handling
|
||||
// We call the destroy window on every viewport (including the main viewport, index 0) to give a chance to the back-end
|
||||
// to clear any data they may have stored in e.g. PlatformUserData, RendererUserData.
|
||||
// It is convenient for the platform back-end code to store something in the main viewport, in order for e.g. the mouse handling
|
||||
// code to operator a consistent manner.
|
||||
// It is expected that the back-end can handle calls to Renderer_DestroyWindow/Platform_DestroyWindow without
|
||||
// crashing if it doesn't have data stored.
|
||||
// crashing if it doesn't have data stored.
|
||||
ImGuiContext& g = *GImGui;
|
||||
for (int i = 0; i < g.Viewports.Size; i++)
|
||||
DestroyPlatformWindow(g.Viewports[i]);
|
||||
@ -11172,7 +11236,7 @@ struct ImGuiDockRequest
|
||||
{
|
||||
ImGuiDockRequestType Type;
|
||||
ImGuiWindow* DockTargetWindow; // Destination/Target Window to dock into (may be a loose window or a DockNode, might be NULL in which case DockTargetNode cannot be NULL)
|
||||
ImGuiDockNode* DockTargetNode; // Destination/Target Node to dock into
|
||||
ImGuiDockNode* DockTargetNode; // Destination/Target Node to dock into
|
||||
ImGuiWindow* DockPayload; // Source/Payload window to dock (may be a loose window or a DockNode), [Optional]
|
||||
ImGuiDir DockSplitDir;
|
||||
float DockSplitRatio;
|
||||
@ -11397,7 +11461,7 @@ void ImGui::DockContextUpdateUndocking(ImGuiContext* ctx)
|
||||
DockBuilderRemoveNodeChildNodes(node->ID);
|
||||
//dc->WantFullRebuild = true;
|
||||
}
|
||||
|
||||
|
||||
// Process full rebuild
|
||||
#if 0
|
||||
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
|
||||
@ -11999,7 +12063,7 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, b
|
||||
{
|
||||
DockNodeAddTabBar(node);
|
||||
node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID;
|
||||
|
||||
|
||||
// Add existing windows
|
||||
for (int n = 0; n < node->Windows.Size - 1; n++)
|
||||
TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
|
||||
@ -12367,7 +12431,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
||||
// N+2: DockNodeUpdate(): node can create host window / Begin(): window becomes visible
|
||||
// We could remove this frame if we could reliably calculate the expected window size during node update, before the Begin() code.
|
||||
// It would require a generalization of CalcWindowExpectedSize(), probably extracting code away from Begin().
|
||||
// In reality it isn't very important as user quickly ends up with size data in .ini file.
|
||||
// In reality it isn't very important as user quickly ends up with size data in .ini file.
|
||||
if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
|
||||
{
|
||||
IM_ASSERT(node->Windows.Size > 0);
|
||||
@ -12459,7 +12523,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
||||
// We set ImGuiWindowFlags_NoFocusOnAppearing because we don't want the host window to take full focus (e.g. steal NavWindow)
|
||||
// But we still it bring it to the front of display. There's no way to choose this precise behavior via window flags.
|
||||
// One simple case to ponder if: window A has a toggle to create windows B/C/D. Dock B/C/D together, clear the toggle and enable it again.
|
||||
// When reappearing B/C/D will request focus and be moved to the top of the display pile, but they are not linked to the dock host window
|
||||
// When reappearing B/C/D will request focus and be moved to the top of the display pile, but they are not linked to the dock host window
|
||||
// during the frame they appear. The dock host window would keep its old display order, and the sorting in EndFrame would move B/C/D back
|
||||
// after the dock host window, losing their top-most status.
|
||||
if (node->HostWindow->Appearing)
|
||||
@ -13035,7 +13099,7 @@ static void ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// There is an edge case when docking into a dockspace which only has inactive nodes.
|
||||
// In this case DockNodeTreeFindNodeByPos() will have selected a leaf node which is inactive.
|
||||
// In this case DockNodeTreeFindNodeByPos() will have selected a leaf node which is inactive.
|
||||
// Because the inactive leaf node doesn't have proper pos/size yet, we'll use the root node as reference.
|
||||
ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
|
||||
if (ref_node_for_rect)
|
||||
@ -13206,7 +13270,7 @@ static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDock
|
||||
overlay_draw_lists[overlay_n]->AddLine(ImVec2(draw_r_in.Min.x, center.y), ImVec2(draw_r_in.Max.x, center.y), overlay_col_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Stop after ImGuiDir_None
|
||||
if ((host_node && (host_node->GetMergedFlags() & ImGuiDockNodeFlags_NoSplit)) || g.IO.ConfigDockingNoSplit)
|
||||
return;
|
||||
@ -13552,7 +13616,7 @@ ImGuiDockNode* ImGui::DockNodeTreeFindNodeByPos(ImGuiDockNode* node, ImVec2 pos)
|
||||
return node->CentralNode;
|
||||
return DockNodeTreeFindFallbackLeafNode(node);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -13684,7 +13748,7 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags fla
|
||||
}
|
||||
|
||||
// Tips: Use with ImGuiDockNodeFlags_PassthruCentralNode!
|
||||
// The limitation with this call is that your window won't have a menu bar.
|
||||
// The limitation with this call is that your window won't have a menu bar.
|
||||
// Even though we could pass window flags, it would also require the user to be able to call BeginMenuBar() somehow meaning we can't Begin/End in a single function.
|
||||
// So if you want a menu bar you need to repeat this code manually ourselves. As with advanced other Docking API, we may change this function signature.
|
||||
ImGuiID ImGui::DockSpaceOverViewport(ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags, const ImGuiWindowClass* window_class)
|
||||
@ -13933,7 +13997,7 @@ void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id, bool clear_persi
|
||||
|
||||
// If 'out_id_at_dir' or 'out_id_at_opposite_dir' are non NULL, the function will write out the ID of the two new nodes created.
|
||||
// Return value is ID of the node at the specified direction, so same as (*out_id_at_dir) if that pointer is set.
|
||||
// FIXME-DOCK: We are not exposing nor using split_outer.
|
||||
// FIXME-DOCK: We are not exposing nor using split_outer.
|
||||
ImGuiID ImGui::DockBuilderSplitNode(ImGuiID id, ImGuiDir split_dir, float size_ratio_for_node_at_dir, ImGuiID* out_id_at_dir, ImGuiID* out_id_at_opposite_dir)
|
||||
{
|
||||
ImGuiContext* ctx = GImGui;
|
||||
@ -14081,7 +14145,7 @@ void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_docks
|
||||
|
||||
if (dst_dock_id != 0)
|
||||
{
|
||||
// Docked windows gets redocked into the new node hierarchy.
|
||||
// Docked windows gets redocked into the new node hierarchy.
|
||||
IMGUI_DEBUG_LOG_DOCKING("Remap live window '%s' 0x%08X -> '%s' 0x%08X\n", src_window_name, src_dock_id, dst_window_name, dst_dock_id);
|
||||
DockBuilderDockWindow(dst_window_name, dst_dock_id);
|
||||
}
|
||||
@ -14107,7 +14171,7 @@ void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_docks
|
||||
if (src_windows.contains(window->ID))
|
||||
continue;
|
||||
|
||||
// Docked windows gets redocked into the new node hierarchy.
|
||||
// Docked windows gets redocked into the new node hierarchy.
|
||||
IMGUI_DEBUG_LOG_DOCKING("Remap window '%s' %08X -> %08X\n", window->Name, src_dock_id, dst_dock_id);
|
||||
DockBuilderDockWindow(window->Name, dst_dock_id);
|
||||
}
|
||||
@ -14360,7 +14424,7 @@ void ImGui::BeginAsDockableDragDropTarget(ImGuiWindow* window)
|
||||
const bool is_explicit_target = g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max);
|
||||
|
||||
// Preview docking request and find out split direction/ratio
|
||||
//const bool do_preview = true; // Ignore testing for payload->IsPreview() which removes one frame of delay, but breaks overlapping drop targets within the same window.
|
||||
//const bool do_preview = true; // Ignore testing for payload->IsPreview() which removes one frame of delay, but breaks overlapping drop targets within the same window.
|
||||
const bool do_preview = payload->IsPreview() || payload->IsDelivery();
|
||||
if (do_preview && (node != NULL || allow_null_target_node))
|
||||
{
|
||||
@ -14692,7 +14756,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
|
||||
|
||||
ItemCount item_count = 0;
|
||||
PasteboardGetItemCount(main_clipboard, &item_count);
|
||||
for (int i = 0; i < item_count; i++)
|
||||
for (ItemCount i = 0; i < item_count; i++)
|
||||
{
|
||||
PasteboardItemID item_id = 0;
|
||||
PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
|
||||
@ -15096,8 +15160,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
for (int i = 0; i < g.PlatformIO.Monitors.Size; i++)
|
||||
{
|
||||
const ImGuiPlatformMonitor& mon = g.PlatformIO.Monitors[i];
|
||||
ImGui::BulletText("Monitor #%d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)",
|
||||
i, mon.DpiScale * 100.0f,
|
||||
ImGui::BulletText("Monitor #%d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)",
|
||||
i, mon.DpiScale * 100.0f,
|
||||
mon.MainPos.x, mon.MainPos.y, mon.MainPos.x + mon.MainSize.x, mon.MainPos.y + mon.MainSize.y, mon.MainSize.x, mon.MainSize.y,
|
||||
mon.WorkPos.x, mon.WorkPos.y, mon.WorkPos.x + mon.WorkSize.x, mon.WorkPos.y + mon.WorkSize.y, mon.WorkSize.x, mon.WorkSize.y);
|
||||
}
|
||||
|
Reference in New Issue
Block a user