| 2641 | // Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) |
| 2642 | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> |
| 2643 | float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) |
| 2644 | { |
| 2645 | if (v_min == v_max) |
| 2646 | return 0.0f; |
| 2647 | IM_UNUSED(data_type); |
| 2648 | |
| 2649 | const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); |
| 2650 | if (is_logarithmic) |
| 2651 | { |
| 2652 | bool flipped = v_max < v_min; |
| 2653 | |
| 2654 | if (flipped) // Handle the case where the range is backwards |
| 2655 | ImSwap(v_min, v_max); |
| 2656 | |
| 2657 | // Fudge min/max to avoid getting close to log(0) |
| 2658 | FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min; |
| 2659 | FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max; |
| 2660 | |
| 2661 | // Awkward special cases - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon) |
| 2662 | if ((v_min == 0.0f) && (v_max < 0.0f)) |
| 2663 | v_min_fudged = -logarithmic_zero_epsilon; |
| 2664 | else if ((v_max == 0.0f) && (v_min < 0.0f)) |
| 2665 | v_max_fudged = -logarithmic_zero_epsilon; |
| 2666 | |
| 2667 | float result; |
| 2668 | if (v_clamped <= v_min_fudged) |
| 2669 | result = 0.0f; // Workaround for values that are in-range but below our fudge |
| 2670 | else if (v_clamped >= v_max_fudged) |
| 2671 | result = 1.0f; // Workaround for values that are in-range but above our fudge |
| 2672 | else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions |
| 2673 | { |
| 2674 | float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine) |
| 2675 | float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; |
| 2676 | float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize; |
| 2677 | if (v == 0.0f) |
| 2678 | result = zero_point_center; // Special case for exactly zero |
| 2679 | else if (v < 0.0f) |
| 2680 | result = (1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(-v_min_fudged / logarithmic_zero_epsilon))) * zero_point_snap_L; |
| 2681 | else |
| 2682 | result = zero_point_snap_R + ((float)(ImLog((FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(v_max_fudged / logarithmic_zero_epsilon)) * (1.0f - zero_point_snap_R)); |
| 2683 | } |
| 2684 | else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider |
| 2685 | result = 1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / -v_max_fudged) / ImLog(-v_min_fudged / -v_max_fudged)); |
| 2686 | else |
| 2687 | result = (float)(ImLog((FLOATTYPE)v_clamped / v_min_fudged) / ImLog(v_max_fudged / v_min_fudged)); |
| 2688 | |
| 2689 | return flipped ? (1.0f - result) : result; |
| 2690 | } |
| 2691 | else |
| 2692 | { |
| 2693 | // Linear slider |
| 2694 | return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min)); |
| 2695 | } |
| 2696 | } |
| 2697 | |
| 2698 | // Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) |
| 2699 | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> |