Nav: Fixed an assert in certain circumstance (mostly when using popups) when mouse positions stop being valid. (#2168) + adding a else block to make NavCalcPreferredRefPos() more explicit.

This commit is contained in:
omar 2018-11-15 13:53:53 +01:00
parent f52f0a5277
commit aa668c410a
3 changed files with 20 additions and 10 deletions

View File

@ -46,6 +46,7 @@ Other Changes:
accidental alteration of window position. We now round the provided size. (#2067) accidental alteration of window position. We now round the provided size. (#2067)
- Nav, Focus: Fixed ImGuiWindowFlags_NoBringToFrontOnFocus windows not being restoring focus - Nav, Focus: Fixed ImGuiWindowFlags_NoBringToFrontOnFocus windows not being restoring focus
properly after the main menu bar or last focused window is deactivated. properly after the main menu bar or last focused window is deactivated.
- Nav: Fixed an assert in certain circumstance (mostly when using popups) when mouse positions stop being valid. (#2168)
- DragFloat: Fixed a situation where dragging with value rounding enabled or with a power curve - DragFloat: Fixed a situation where dragging with value rounding enabled or with a power curve
erroneously wrapped the value to one of the min/max edge. (#2024, #708, #320, #2075). erroneously wrapped the value to one of the min/max edge. (#2024, #708, #320, #2075).
- DragFloat: Disabled using power curve when one edge is FLT_MAX (broken in 1.61). (#2024) - DragFloat: Disabled using power curve when one edge is FLT_MAX (broken in 1.61). (#2024)

View File

@ -2966,7 +2966,7 @@ static void ImGui::UpdateMouseInputs()
// Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well) // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
if (IsMousePosValid(&g.IO.MousePos)) if (IsMousePosValid(&g.IO.MousePos))
g.IO.MousePos = ImFloor(g.IO.MousePos); g.IO.MousePos = g.LastValidMousePos = ImFloor(g.IO.MousePos);
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))
@ -6415,8 +6415,8 @@ void ImGui::OpenPopupEx(ImGuiID id)
popup_ref.ParentWindow = parent_window; popup_ref.ParentWindow = parent_window;
popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenFrameCount = g.FrameCount;
popup_ref.OpenParentId = parent_window->IDStack.back(); popup_ref.OpenParentId = parent_window->IDStack.back();
popup_ref.OpenMousePos = g.IO.MousePos;
popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
//printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id); //printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id);
if (g.OpenPopupStack.Size < current_stack_size + 1) if (g.OpenPopupStack.Size < current_stack_size + 1)
@ -7093,13 +7093,20 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
return ImFloor(g.IO.MousePos); {
// Mouse (we need a fallback in case the mouse becomes invalid after being used)
// When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item if (IsMousePosValid(&g.IO.MousePos))
const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; return g.IO.MousePos;
ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); return g.LastValidMousePos;
ImRect visible_rect = GetViewportRect(); }
return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. else
{
// When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
ImRect visible_rect = GetViewportRect();
return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta.
}
} }
float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)

View File

@ -687,8 +687,9 @@ struct ImGuiContext
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
ImVec2 LastValidMousePos;
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent) ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
@ -833,6 +834,7 @@ struct ImGuiContext
ActiveIdSource = ImGuiInputSource_None; ActiveIdSource = ImGuiInputSource_None;
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
LastValidMousePos = ImVec2(0.0f, 0.0f);
MovingWindow = NULL; MovingWindow = NULL;
NextTreeNodeOpenVal = false; NextTreeNodeOpenVal = false;
NextTreeNodeOpenCond = 0; NextTreeNodeOpenCond = 0;