@ -2615,7 +2615,6 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
v_max_fudged = - logarithmic_zero_epsilon ;
float result ;
if ( v_clamped < = v_min_fudged )
result = 0.0f ; // Workaround for values that are in-range but below our fudge
else if ( v_clamped > = v_max_fudged )
@ -2639,91 +2638,81 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
return flipped ? ( 1.0f - result ) : result ;
}
// Linear slider
return ( float ) ( ( FLOATTYPE ) ( SIGNEDTYPE ) ( v_clamped - v_min ) / ( FLOATTYPE ) ( SIGNEDTYPE ) ( v_max - v_min ) ) ;
else
{
// Linear slider
return ( float ) ( ( FLOATTYPE ) ( SIGNEDTYPE ) ( v_clamped - v_min ) / ( FLOATTYPE ) ( SIGNEDTYPE ) ( v_max - v_min ) ) ;
}
}
// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT)
template < typename TYPE , typename SIGNEDTYPE , typename FLOATTYPE >
TYPE ImGui : : ScaleValueFromRatioT ( ImGuiDataType data_type , float t , TYPE v_min , TYPE v_max , bool is_logarithmic , float logarithmic_zero_epsilon , float zero_deadzone_halfsize )
{
if ( v_min = = v_max )
// We special-case the extents because otherwise our logarithmic fudging can lead to "mathematically correct"
// but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value. Also generally simpler.
if ( t < = 0.0f | | v_min = = v_max )
return v_min ;
const bool is_floating_point = ( data_type = = ImGuiDataType_Float ) | | ( data_type = = ImGuiDataType_Double ) ;
if ( t > = 1.0f )
return v_max ;
TYPE result ;
TYPE result = ( TYPE ) 0 ;
if ( is_logarithmic )
{
// We special-case the extents because otherwise our fudging can lead to "mathematically correct" but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value
if ( t < = 0.0f )
result = v_min ;
else if ( t > = 1.0f )
result = v_max ;
else
{
bool flipped = v_max < v_min ; // Check if range is "backwards"
// Fudge min/max to avoid getting silly results close to zero
FLOATTYPE v_min_fudged = ( ImAbs ( ( FLOATTYPE ) v_min ) < logarithmic_zero_epsilon ) ? ( ( v_min < 0.0f ) ? - logarithmic_zero_epsilon : logarithmic_zero_epsilon ) : ( FLOATTYPE ) v_min ;
FLOATTYPE v_max_fudged = ( ImAbs ( ( FLOATTYPE ) v_max ) < logarithmic_zero_epsilon ) ? ( ( v_max < 0.0f ) ? - logarithmic_zero_epsilon : logarithmic_zero_epsilon ) : ( FLOATTYPE ) v_max ;
// Fudge min/max to avoid getting silly results close to zero
FLOATTYPE v_min_fudged = ( ImAbs ( ( FLOATTYPE ) v_min ) < logarithmic_zero_epsilon ) ? ( ( v_min < 0.0f ) ? - logarithmic_zero_epsilon : logarithmic_zero_epsilon ) : ( FLOATTYPE ) v_min ;
FLOATTYPE v_max_fudged = ( ImAbs ( ( FLOATTYPE ) v_max ) < logarithmic_zero_epsilon ) ? ( ( v_max < 0.0f ) ? - logarithmic_zero_epsilon : logarithmic_zero_epsilon ) : ( FLOATTYPE ) v_max ;
if ( flipped )
ImSwap ( v_min_fudged , v_max_fudged ) ;
const bool flipped = v_max < v_min ; // Check if range is "backwards"
if ( flipped )
ImSwap ( v_min_fudged , v_max_fudged ) ;
// Awkward special case - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon)
if ( ( v_max = = 0.0f ) & & ( v_min < 0.0f ) )
v_max_fudged = - logarithmic_zero_epsilon ;
// Awkward special case - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon)
if ( ( v_max = = 0.0f ) & & ( v_min < 0.0f ) )
v_max_fudged = - logarithmic_zero_epsilon ;
float t_with_flip = flipped ? ( 1.0f - t ) : t ; // t, but flipped if necessary to account for us flipping the range
float t_with_flip = flipped ? ( 1.0f - t ) : t ; // t, but flipped if necessary to account for us flipping the range
if ( ( v_min * v_max ) < 0.0f ) // Range crosses zero, so we have to do this in two parts
{
float zero_point_center = ( - ( float ) ImMin ( v_min , v_max ) ) / ImAbs ( ( float ) v_max - ( float ) v_min ) ; // The zero point in parametric space
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize ;
float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize ;
if ( t_with_flip > = zero_point_snap_L & & t_with_flip < = zero_point_snap_R )
result = ( TYPE ) 0.0f ; // Special case to make getting exactly zero possible (the epsilon prevents it otherwise)
else if ( t_with_flip < zero_point_center )
result = ( TYPE ) - ( logarithmic_zero_epsilon * ImPow ( - v_min_fudged / logarithmic_zero_epsilon , ( FLOATTYPE ) ( 1.0f - ( t_with_flip / zero_point_snap_L ) ) ) ) ;
else
result = ( TYPE ) ( logarithmic_zero_epsilon * ImPow ( v_max_fudged / logarithmic_zero_epsilon , ( FLOATTYPE ) ( ( t_with_flip - zero_point_snap_R ) / ( 1.0f - zero_point_snap_R ) ) ) ) ;
}
else if ( ( v_min < 0.0f ) | | ( v_max < 0.0f ) ) // Entirely negative slider
result = ( TYPE ) - ( - v_max_fudged * ImPow ( - v_min_fudged / - v_max_fudged , ( FLOATTYPE ) ( 1.0f - t_with_flip ) ) ) ;
if ( ( v_min * v_max ) < 0.0f ) // Range crosses zero, so we have to do this in two parts
{
float zero_point_center = ( - ( float ) ImMin ( v_min , v_max ) ) / ImAbs ( ( float ) v_max - ( float ) v_min ) ; // The zero point in parametric space
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize ;
float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize ;
if ( t_with_flip > = zero_point_snap_L & & t_with_flip < = zero_point_snap_R )
result = ( TYPE ) 0.0f ; // Special case to make getting exactly zero possible (the epsilon prevents it otherwise)
else if ( t_with_flip < zero_point_center )
result = ( TYPE ) - ( logarithmic_zero_epsilon * ImPow ( - v_min_fudged / logarithmic_zero_epsilon , ( FLOATTYPE ) ( 1.0f - ( t_with_flip / zero_point_snap_L ) ) ) ) ;
else
result = ( TYPE ) ( v_min_fudged * ImPow ( v_max_fudged / v_min_fudged , ( FLOATTYPE ) t_with_flip ) ) ;
result = ( TYPE ) ( logarithmic_zero_epsilon * ImPow ( v_max_fudged / logarithmic_zero_epsilon , ( FLOATTYPE ) ( ( t_with_flip - zero_point_snap_R ) / ( 1.0f - zero_point_snap_R ) ) ) ) ;
}
else if ( ( v_min < 0.0f ) | | ( v_max < 0.0f ) ) // Entirely negative slider
result = ( TYPE ) - ( - v_max_fudged * ImPow ( - v_min_fudged / - v_max_fudged , ( FLOATTYPE ) ( 1.0f - t_with_flip ) ) ) ;
else
result = ( TYPE ) ( v_min_fudged * ImPow ( v_max_fudged / v_min_fudged , ( FLOATTYPE ) t_with_flip ) ) ;
}
else
{
// Linear slider
const bool is_floating_point = ( data_type = = ImGuiDataType_Float ) | | ( data_type = = ImGuiDataType_Double ) ;
if ( is_floating_point )
{
result = ImLerp ( v_min , v_max , t ) ;
}
else
else if ( t < 1.0 )
{
// - For integer values we want the clicking position to match the grab box so we round above
// This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
// - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64
// range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits.
if ( t < 1.0 )
{
FLOATTYPE v_new_off_f = ( SIGNEDTYPE ) ( v_max - v_min ) * t ;
result = ( TYPE ) ( ( SIGNEDTYPE ) v_min + ( SIGNEDTYPE ) ( v_new_off_f + ( FLOATTYPE ) ( v_min > v_max ? - 0.5 : 0.5 ) ) ) ;
}
else
{
result = v_max ;
}
FLOATTYPE v_new_off_f = ( SIGNEDTYPE ) ( v_max - v_min ) * t ;
result = ( TYPE ) ( ( SIGNEDTYPE ) v_min + ( SIGNEDTYPE ) ( v_new_off_f + ( FLOATTYPE ) ( v_min > v_max ? - 0.5 : 0.5 ) ) ) ;
}
}
return result ;
}
// FIXME: Move more of the code into SliderBehavior()
// FIXME: Try to move more of the code into shared SliderBehavior()
template < typename TYPE , typename SIGNEDTYPE , typename FLOATTYPE >
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 )
{
@ -2733,13 +2722,14 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
const ImGuiAxis axis = ( flags & ImGuiSliderFlags_Vertical ) ? ImGuiAxis_Y : ImGuiAxis_X ;
const bool is_logarithmic = ( flags & ImGuiSliderFlags_Logarithmic ) ! = 0 ;
const bool is_floating_point = ( data_type = = ImGuiDataType_Float ) | | ( data_type = = ImGuiDataType_Double ) ;
const SIGNEDTYPE v_range = ( v_min < v_max ? v_max - v_min : v_min - v_max ) ;
const float grab_padding = 2.0f ;
// Calculate bounds
const float grab_padding = 2.0f ; // FIXME: Should be part of style.
const float slider_sz = ( bb . Max [ axis ] - bb . Min [ axis ] ) - grab_padding * 2.0f ;
float grab_sz = style . GrabMinSize ;
SIGNEDTYPE v_range = ( v_min < v_max ? v_max - v_min : v_min - v_max ) ;
if ( ! is_floating_point & & v_range > = 0 ) // v_range < 0 may happen on integer overflows
grab_sz = ImMax ( ( float ) ( slider_sz / ( v_range + 1 ) ) , style . GrabMinSize ) ; // For integer sliders: if possible have the grab size represent 1 unit
if ( ! is_floating_point & & v_range > = 0 ) // v_range < 0 may happen on integer overflows
grab_sz = ImMax ( ( float ) ( slider_sz / ( v_range + 1 ) ) , style . GrabMinSize ) ; // For integer sliders: if possible have the grab size represent 1 unit
grab_sz = ImMin ( grab_sz , slider_sz ) ;
const float slider_usable_sz = slider_sz - grab_sz ;
const float slider_usable_pos_min = bb . Min [ axis ] + grab_padding + grab_sz * 0.5f ;
@ -2770,7 +2760,8 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
else
{
const float mouse_abs_pos = g . IO . MousePos [ axis ] ;
clicked_t = ( slider_usable_sz > 0.0f ) ? ImClamp ( ( mouse_abs_pos - slider_usable_pos_min ) / slider_usable_sz , 0.0f , 1.0f ) : 0.0f ;
if ( slider_usable_sz > 0.0f )
clicked_t = ImSaturate ( ( mouse_abs_pos - slider_usable_pos_min ) / slider_usable_sz ) ;
if ( axis = = ImGuiAxis_Y )
clicked_t = 1.0f - clicked_t ;
set_new_value = true ;