From 907268a4305b77920a94453214a35637e981b0ab Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 22:31:07 +0100 Subject: [PATCH] MultiSelect: Box-Select: Fixed scrolling on high framerates. --- imgui_internal.h | 1 + imgui_widgets.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 8e71683f4..7c0c6aa22 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1721,6 +1721,7 @@ struct ImGuiBoxSelectState ImGuiKeyChord KeyMods : 16; // Latched key-mods for box-select logic. ImVec2 StartPosRel; // Start position in window-contents relative space (to support scrolling) ImVec2 EndPosRel; // End position in window-contents relative space + ImVec2 ScrollAccum; // Scrolling accumulator (to behave at high-frame spaces) ImGuiWindow* Window; // Temporary/Transient data diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7f3e529ca..14d4cac64 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7127,11 +7127,14 @@ static void BoxSelectStart(ImGuiID id, ImGuiSelectionUserData clicked_item) bs->IsStartedFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid); bs->KeyMods = g.IO.KeyMods; bs->StartPosRel = bs->EndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos); + bs->ScrollAccum = ImVec2(0.0f, 0.0f); } static void BoxSelectScrollWithMouseDrag(ImGuiWindow* window, const ImRect& inner_r) { ImGuiContext& g = *GImGui; + ImGuiBoxSelectState* bs = &g.BoxSelectState; + IM_ASSERT(bs->Window == window); for (int n = 0; n < 2; n++) // each axis { const float mouse_pos = g.IO.MousePos[n]; @@ -7139,12 +7142,20 @@ static void BoxSelectScrollWithMouseDrag(ImGuiWindow* window, const ImRect& inne const float scroll_curr = window->Scroll[n]; if (dist == 0.0f || (dist < 0.0f && scroll_curr < 0.0f) || (dist > 0.0f && scroll_curr >= window->ScrollMax[n])) continue; + const float speed_multiplier = ImLinearRemapClamp(g.FontSize, g.FontSize * 5.0f, 1.0f, 4.0f, ImAbs(dist)); // x1 to x4 depending on distance - const float scroll_step = IM_ROUND(g.FontSize * 35.0f * speed_multiplier * ImSign(dist) * g.IO.DeltaTime); + const float scroll_step = g.FontSize * 35.0f * speed_multiplier * ImSign(dist) * g.IO.DeltaTime; + bs->ScrollAccum[n] += scroll_step; + + // Accumulate into a stored value so we can handle high-framerate + const float scroll_step_i = ImFloor(bs->ScrollAccum[n]); + if (scroll_step_i == 0.0f) + continue; if (n == 0) - ImGui::SetScrollX(window, scroll_curr + scroll_step); + ImGui::SetScrollX(window, scroll_curr + scroll_step_i); else - ImGui::SetScrollY(window, scroll_curr + scroll_step); + ImGui::SetScrollY(window, scroll_curr + scroll_step_i); + bs->ScrollAccum[n] -= scroll_step_i; } }