| 2692 | // FIXME: Try to move more of the code into shared SliderBehavior() |
| 2693 | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> |
| 2694 | bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb) |
| 2695 | { |
| 2696 | ImGuiContext& g = *GImGui; |
| 2697 | const ImGuiStyle& style = g.Style; |
| 2698 | |
| 2699 | const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; |
| 2700 | const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0; |
| 2701 | const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); |
| 2702 | const SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max); |
| 2703 | |
| 2704 | // Calculate bounds |
| 2705 | const float grab_padding = 2.0f; // FIXME: Should be part of style. |
| 2706 | const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f; |
| 2707 | float grab_sz = style.GrabMinSize; |
| 2708 | if (!is_floating_point && v_range >= 0) // v_range < 0 may happen on integer overflows |
| 2709 | grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit |
| 2710 | grab_sz = ImMin(grab_sz, slider_sz); |
| 2711 | const float slider_usable_sz = slider_sz - grab_sz; |
| 2712 | const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f; |
| 2713 | const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f; |
| 2714 | |
| 2715 | float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true |
| 2716 | float zero_deadzone_halfsize = 0.0f; // Only valid when is_logarithmic is true |
| 2717 | if (is_logarithmic) |
| 2718 | { |
| 2719 | // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound. |
| 2720 | const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1; |
| 2721 | logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); |
| 2722 | zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f); |
| 2723 | } |
| 2724 | |
| 2725 | // Process interacting with the slider |
| 2726 | bool value_changed = false; |
| 2727 | if (g.ActiveId == id) |
| 2728 | { |
| 2729 | bool set_new_value = false; |
| 2730 | float clicked_t = 0.0f; |
| 2731 | if (g.ActiveIdSource == ImGuiInputSource_Mouse) |
| 2732 | { |
| 2733 | if (!g.IO.MouseDown[0]) |
| 2734 | { |
| 2735 | ClearActiveID(); |
| 2736 | } |
| 2737 | else |
| 2738 | { |
| 2739 | const float mouse_abs_pos = g.IO.MousePos[axis]; |
| 2740 | if (g.ActiveIdIsJustActivated) |
| 2741 | { |
| 2742 | float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |
| 2743 | if (axis == ImGuiAxis_Y) |
| 2744 | grab_t = 1.0f - grab_t; |
| 2745 | const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); |
| 2746 | const bool clicked_around_grab = (mouse_abs_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_abs_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here. |
| 2747 | g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_abs_pos - grab_pos : 0.0f; |
| 2748 | } |
| 2749 | if (slider_usable_sz > 0.0f) |
| 2750 | clicked_t = ImSaturate((mouse_abs_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz); |
| 2751 | if (axis == ImGuiAxis_Y) |
nothing calls this directly
no test coverage detected