Drags: fixed handling of ImGuiSliderFlags_WrapAround when dragging fast. (#9612, #9611, #7749)

This commit is contained in:
ocornut 2026-11-05 12:38:19 +01:00
parent a1af3c1a59
commit 253aa51aba
4 changed files with 12 additions and 4 deletions

View File

@ -96,6 +96,8 @@ Other Changes:
- Multi-Select: - Multi-Select:
- Fixed `ImGuiSelectionBasicStorage::GetNextSelectedItem()` reading one past the - Fixed `ImGuiSelectionBasicStorage::GetNextSelectedItem()` reading one past the
end of storage when trailing items are unselected (#9604) [@MilosLord] end of storage when trailing items are unselected (#9604) [@MilosLord]
- Drags: fixed handling of `ImGuiSliderFlags_WrapAround`: value could temporarily
escape the range when dragging fast. (#9612, #9611, #7749) [@swayie, @ocornut]
- ImVec2: added a check for cases where a custom `IM_VEC2_CLASS_EXTRA` macro - ImVec2: added a check for cases where a custom `IM_VEC2_CLASS_EXTRA` macro
adds an extra `operator=` to ImVec2. This isn't supported but should not adds an extra `operator=` to ImVec2. This isn't supported but should not
be needed as you should have a constructor to convert from your type to ImVec2. be needed as you should have a constructor to convert from your type to ImVec2.

View File

@ -1842,6 +1842,7 @@ static void DemoWindowWidgetsDragsAndSliders()
//ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags); // To test ClampZeroRange //ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags); // To test ClampZeroRange
//ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags); //ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags);
ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags); ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
ImGui::DragFloat("DragFloat (0 -> 100)", &drag_f, 0.2f, 0, 100, "%.2f", flags);
ImGui::DragFloat4("DragFloat4 (0 -> 1)", drag_f4, 0.005f, 0.0f, 1.0f, "%.3f", flags); // Multi-component item, mostly here to document the effect of ImGuiSliderFlags_ColorMarkers. ImGui::DragFloat4("DragFloat4 (0 -> 1)", drag_f4, 0.005f, 0.0f, 1.0f, "%.3f", flags); // Multi-component item, mostly here to document the effect of ImGuiSliderFlags_ColorMarkers.
// Sliders // Sliders

View File

@ -531,6 +531,9 @@ template<typename T> T ImLerp(T a, T b, float t) { return
template<typename T> void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template<typename T> void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
template<typename T> T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; } template<typename T> T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
template<typename T> T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; } template<typename T> T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
inline float ImMod(float a, float b) { return ImFmod(a, b); }
inline double ImMod(double a, double b) { return (double)ImFmod((float)a, (float)b); } // FIXME
template<typename T> T ImMod(T a, T b) { return a % b; }
// - Misc maths helpers // - Misc maths helpers
inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); }
inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); }

View File

@ -2650,10 +2650,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (is_wrapped) if (is_wrapped)
{ {
// Wrap values // Wrap values
if (v_cur < v_min) const TYPE range = v_max - v_min + (is_floating_point ? 0 : 1);
v_cur += v_max - v_min + (is_floating_point ? 0 : 1); TYPE offset = ImMod((TYPE)(v_cur - v_min), range);
if (v_cur > v_max) if (offset < 0)
v_cur -= v_max - v_min + (is_floating_point ? 0 : 1); offset += range;
v_cur = (TYPE)(v_min + offset);
IM_ASSERT_PARANOID(v_cur >= v_min && v_cur <= v_max);
} }
else else
{ {