Merge branch 'master' into docking

# Conflicts:
#	docs/CHANGELOG.txt
#	imgui.cpp
This commit is contained in:
ocornut
2021-10-11 19:25:50 +02:00
12 changed files with 192 additions and 106 deletions

149
imgui.cpp
View File

@ -1,4 +1,4 @@
// dear imgui, v1.85 WIP
// dear imgui, v1.85
// (main code and documentation)
// Help:
@ -390,7 +390,7 @@ CODE
- 2021/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead.
- 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful.
- 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
- ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
- ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
@ -3366,7 +3366,6 @@ void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id)
// Increment counters
// FIXME: ImGuiItemFlags_Disabled should disable more.
const bool is_tab_stop = (g.LastItemData.InFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->DC.FocusCounterRegular++;
if (is_tab_stop)
{
window->DC.FocusCounterTabStop++;
@ -3385,11 +3384,6 @@ void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id)
// Handle focus requests
if (g.TabFocusRequestCurrWindow == window)
{
if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
{
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByCode;
return;
}
if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{
g.NavJustTabbedId = id; // FIXME-NAV: aim to eventually set in NavUpdate() once we finish the refactor
@ -3977,7 +3971,10 @@ void ImGui::UpdateTabFocus()
ImGuiContext& g = *GImGui;
// Pressing TAB activate widget focus
g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab));
g.TabFocusPressed = false;
if (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
if (!g.IO.KeyCtrl && !g.IO.KeyAlt && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab))
g.TabFocusPressed = true;
if (g.ActiveId == 0 && g.TabFocusPressed)
{
// - This path is only taken when no widget are active/tabbed-into yet.
@ -3985,7 +3982,6 @@ void ImGui::UpdateTabFocus()
// - Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields here even though they will be turned into Curr fields below.
g.TabFocusRequestNextWindow = g.NavWindow;
g.TabFocusRequestNextCounterRegular = INT_MAX;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + (g.IO.KeyShift ? -1 : 0);
else
@ -3994,17 +3990,15 @@ void ImGui::UpdateTabFocus()
// Turn queued focus request into current one
g.TabFocusRequestCurrWindow = NULL;
g.TabFocusRequestCurrCounterRegular = g.TabFocusRequestCurrCounterTabStop = INT_MAX;
g.TabFocusRequestCurrCounterTabStop = INT_MAX;
if (g.TabFocusRequestNextWindow != NULL)
{
ImGuiWindow* window = g.TabFocusRequestNextWindow;
g.TabFocusRequestCurrWindow = window;
if (g.TabFocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
g.TabFocusRequestCurrCounterRegular = ImModPositive(g.TabFocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
if (g.TabFocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
g.TabFocusRequestCurrCounterTabStop = ImModPositive(g.TabFocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
g.TabFocusRequestNextWindow = NULL;
g.TabFocusRequestNextCounterRegular = g.TabFocusRequestNextCounterTabStop = INT_MAX;
g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
g.NavIdTabCounter = INT_MAX;
@ -6790,7 +6784,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.CurrentColumns = NULL;
window->DC.LayoutType = ImGuiLayoutType_Vertical;
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1;
window->DC.FocusCounterTabStop = -1;
window->DC.ItemWidth = window->ItemWidthDefault;
window->DC.TextWrapPos = -1.0f; // disabled
@ -7094,8 +7088,18 @@ void ImGui::FocusWindow(ImGuiWindow* window)
void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window)
{
ImGuiContext& g = *GImGui;
const int start_idx = ((under_this_window != NULL) ? FindWindowFocusIndex(under_this_window) : g.WindowsFocusOrder.Size) - 1;
int start_idx = g.WindowsFocusOrder.Size - 1;
if (under_this_window != NULL)
{
// Aim at root window behind us, if we are in a child window that's our own root (see #4640)
int offset = -1;
while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
{
under_this_window = under_this_window->ParentWindow;
offset = 0;
}
start_idx = FindWindowFocusIndex(under_this_window) + offset;
}
for (int i = start_idx; i >= 0; i--)
{
// We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
@ -7677,12 +7681,16 @@ void ImGui::PopFocusScope()
void ImGui::SetKeyboardFocusHere(int offset)
{
IM_ASSERT(offset >= -1); // -1 is allowed but not below
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
g.TabFocusRequestNextWindow = window;
g.TabFocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset;
g.TabFocusRequestNextCounterTabStop = INT_MAX;
IM_ASSERT(offset >= -1); // -1 is allowed but not below
g.NavWindow = window;
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_None, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
if (offset == -1)
NavMoveRequestResolveWithLastItem();
else
g.NavTabbingInputableRemaining = offset + 1;
}
void ImGui::SetItemDefaultFocus()
@ -7691,15 +7699,17 @@ void ImGui::SetItemDefaultFocus()
ImGuiWindow* window = g.CurrentWindow;
if (!window->Appearing)
return;
if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == window->DC.NavLayerCurrent)
{
g.NavInitRequest = false;
g.NavInitResultId = g.LastItemData.ID;
g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos);
NavUpdateAnyRequestFlag();
if (!IsItemVisible())
SetScrollHereY();
}
if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResultId == 0) || g.NavLayer != window->DC.NavLayerCurrent)
return;
g.NavInitRequest = false;
g.NavInitResultId = g.LastItemData.ID;
g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos);
NavUpdateAnyRequestFlag();
// Scroll could be done in NavInitRequestApplyResult() via a opt-in flag (we however don't want regular init requests to scroll)
if (!IsItemVisible())
ScrollToRectEx(window, g.LastItemData.Rect, ImGuiScrollFlags_None);
}
void ImGui::SetStateStorage(ImGuiStorage* tree)
@ -9625,6 +9635,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
result->Window = window;
result->ID = g.LastItemData.ID;
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
result->InFlags = g.LastItemData.InFlags;
result->RectRel = ImRect(g.LastItemData.NavRect.Min - window->Pos, g.LastItemData.NavRect.Max - window->Pos);
}
@ -9659,18 +9670,30 @@ static void ImGui::NavProcessItem()
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy)
if (g.NavMoveScoringItems)
{
if (item_flags & ImGuiItemFlags_Inputable)
g.NavTabbingInputableRemaining--;
if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
{
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
if (NavScoreItem(result))
NavApplyItemToResult(result);
// Features like PageUp/PageDown need to maintain a separate score for the visible set of items.
const float VISIBLE_RATIO = 0.70f;
if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
if (NavScoreItem(&g.NavMoveResultLocalVisible))
NavApplyItemToResult(&g.NavMoveResultLocalVisible);
if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
{
if (g.NavTabbingInputableRemaining == 0)
NavMoveRequestResolveWithLastItem();
}
else
{
if (NavScoreItem(result))
NavApplyItemToResult(result);
// Features like PageUp/PageDown need to maintain a separate score for the visible set of items.
const float VISIBLE_RATIO = 0.70f;
if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
if (NavScoreItem(&g.NavMoveResultLocalVisible))
NavApplyItemToResult(&g.NavMoveResultLocalVisible);
}
}
}
@ -9696,6 +9719,10 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.NavWindow != NULL);
if (move_flags & ImGuiNavMoveFlags_Tabbing)
move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
g.NavMoveSubmitted = g.NavMoveScoringItems = true;
g.NavMoveDir = move_dir;
g.NavMoveDirForDebug = move_dir;
@ -9704,12 +9731,21 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM
g.NavMoveScrollFlags = scroll_flags;
g.NavMoveForwardToNextFrame = false;
g.NavMoveKeyMods = g.IO.KeyMods;
g.NavTabbingInputableRemaining = 0;
g.NavMoveResultLocal.Clear();
g.NavMoveResultLocalVisible.Clear();
g.NavMoveResultOther.Clear();
NavUpdateAnyRequestFlag();
}
void ImGui::NavMoveRequestResolveWithLastItem()
{
ImGuiContext& g = *GImGui;
g.NavMoveScoringItems = false; // Ensure request doesn't need more processing
NavApplyItemToResult(&g.NavMoveResultLocal);
NavUpdateAnyRequestFlag();
}
void ImGui::NavMoveRequestCancel()
{
ImGuiContext& g = *GImGui;
@ -9933,6 +9969,7 @@ static void ImGui::NavUpdate()
// Process navigation move request
if (g.NavMoveSubmitted)
NavMoveRequestApplyResult();
g.NavTabbingInputableRemaining = 0;
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
// Apply application mouse position movement, after we had a chance to process move request result.
@ -9950,7 +9987,7 @@ static void ImGui::NavUpdate()
}
g.NavIdIsAlive = false;
g.NavJustTabbedId = 0;
IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1);
IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
// Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0
if (g.NavWindow)
@ -10184,7 +10221,9 @@ void ImGui::NavMoveRequestApplyResult()
// In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result)
if (result == NULL)
{
if (g.NavId != 0)
if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
{
g.NavDisableHighlight = false;
g.NavDisableMouseHover = true;
@ -10239,9 +10278,27 @@ void ImGui::NavMoveRequestApplyResult()
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
// Tabbing: Activates Inputable or Focus non-Inputable
if ((g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && (result->InFlags & ImGuiItemFlags_Inputable))
{
g.NavNextActivateId = result->ID;
g.NavNextActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState;
g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
}
// Activate
if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
{
g.NavNextActivateId = result->ID;
g.NavNextActivateFlags = ImGuiActivateFlags_None;
}
// Enable nav highlight
g.NavDisableHighlight = false;
g.NavDisableMouseHover = g.NavMousePosDirty = true;
if ((g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
{
g.NavDisableHighlight = false;
g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
}
// Process NavCancel input (to close a popup, get back to parent, clear focus)
@ -10406,10 +10463,11 @@ static void ImGui::NavEndFrame()
}
do_forward = true;
}
const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
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;
ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y + decoration_up_height;
if (move_flags & ImGuiNavMoveFlags_WrapY)
{
bb_rel.TranslateX(-bb_rel.GetWidth());
@ -10419,7 +10477,7 @@ static void ImGui::NavEndFrame()
}
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
{
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y + decoration_up_height;
if (move_flags & ImGuiNavMoveFlags_WrapY)
{
bb_rel.TranslateX(+bb_rel.GetWidth());
@ -10440,6 +10498,7 @@ static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
ImGuiContext& g = *GImGui;
IM_UNUSED(g);
int order = window->FocusOrder;
IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking)
IM_ASSERT(g.WindowsFocusOrder[order] == window);
return order;
}
@ -16574,7 +16633,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (cfg->ShowStackTool)
ShowStackToolWindow(&cfg->ShowStackTool);
if (!Begin("Dear ImGui Metrics/Debugger", p_open))
if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
{
End();
return;