| 2156 | // This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) |
| 2157 | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> |
| 2158 | bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags) |
| 2159 | { |
| 2160 | ImGuiContext& g = *GImGui; |
| 2161 | const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; |
| 2162 | const bool is_clamped = (v_min < v_max); |
| 2163 | const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0; |
| 2164 | const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); |
| 2165 | |
| 2166 | // Default tweak speed |
| 2167 | if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX)) |
| 2168 | v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); |
| 2169 | |
| 2170 | // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings |
| 2171 | float adjust_delta = 0.0f; |
| 2172 | if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) |
| 2173 | { |
| 2174 | adjust_delta = g.IO.MouseDelta[axis]; |
| 2175 | if (g.IO.KeyAlt) |
| 2176 | adjust_delta *= 1.0f / 100.0f; |
| 2177 | if (g.IO.KeyShift) |
| 2178 | adjust_delta *= 10.0f; |
| 2179 | } |
| 2180 | else if (g.ActiveIdSource == ImGuiInputSource_Nav) |
| 2181 | { |
| 2182 | const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; |
| 2183 | const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); |
| 2184 | const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast); |
| 2185 | const float tweak_factor = tweak_slow ? 1.0f / 1.0f : tweak_fast ? 10.0f : 1.0f; |
| 2186 | adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor; |
| 2187 | v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); |
| 2188 | } |
| 2189 | adjust_delta *= v_speed; |
| 2190 | |
| 2191 | // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter. |
| 2192 | if (axis == ImGuiAxis_Y) |
| 2193 | adjust_delta = -adjust_delta; |
| 2194 | |
| 2195 | // For logarithmic use our range is effectively 0..1 so scale the delta into that range |
| 2196 | if (is_logarithmic && (v_max - v_min < FLT_MAX) && ((v_max - v_min) > 0.000001f)) // Epsilon to avoid /0 |
| 2197 | adjust_delta /= (float)(v_max - v_min); |
| 2198 | |
| 2199 | // Clear current value on activation |
| 2200 | // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. |
| 2201 | bool is_just_activated = g.ActiveIdIsJustActivated; |
| 2202 | bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); |
| 2203 | if (is_just_activated || is_already_past_limits_and_pushing_outward) |
| 2204 | { |
| 2205 | g.DragCurrentAccum = 0.0f; |
| 2206 | g.DragCurrentAccumDirty = false; |
| 2207 | } |
| 2208 | else if (adjust_delta != 0.0f) |
| 2209 | { |
| 2210 | g.DragCurrentAccum += adjust_delta; |
| 2211 | g.DragCurrentAccumDirty = true; |
| 2212 | } |
| 2213 | |
| 2214 | if (!g.DragCurrentAccumDirty) |
| 2215 | return false; |
nothing calls this directly
no test coverage detected