diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bbd5e0ba4..23b05b5b8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -96,6 +96,8 @@ Other Changes: - Multi-Select: - Fixed `ImGuiSelectionBasicStorage::GetNextSelectedItem()` reading one past the 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 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. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5545ecc41..bac1791c3 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -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 (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::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. // Sliders diff --git a/imgui_internal.h b/imgui_internal.h index 57851e7ee..add0b8ce1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -531,6 +531,9 @@ template T ImLerp(T a, T b, float t) { return template void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template 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 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 T ImMod(T a, T b) { return a % b; } // - 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 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); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f36a888c2..62bff5880 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2650,10 +2650,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const if (is_wrapped) { // Wrap values - if (v_cur < v_min) - v_cur += v_max - v_min + (is_floating_point ? 0 : 1); - if (v_cur > v_max) - v_cur -= v_max - v_min + (is_floating_point ? 0 : 1); + const TYPE range = v_max - v_min + (is_floating_point ? 0 : 1); + TYPE offset = ImMod((TYPE)(v_cur - v_min), range); + if (offset < 0) + offset += range; + v_cur = (TYPE)(v_min + offset); + IM_ASSERT_PARANOID(v_cur >= v_min && v_cur <= v_max); } else {