Internals: DragFloat: Fixed power handling. Use an temporary accumulator and no absolute values so we will be able to manipulate double as well as 64-bit integers. (#1011, #708, #320)
This commit is contained in:
parent
3f04fd0644
commit
93b8580a8d
@ -62,6 +62,7 @@ Other Changes:
|
|||||||
- DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this).
|
- DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this).
|
||||||
- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011)
|
- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011)
|
||||||
- DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642)
|
- DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642)
|
||||||
|
- DragFloat: Improved computation when using the power curve. Reduced lost of input precision with small steps. Added an assert than power-curve requires a min/max range. (~#642)
|
||||||
- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre 1.60 navigation branch). (#787)
|
- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre 1.60 navigation branch). (#787)
|
||||||
- Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439)
|
- Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439)
|
||||||
- Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769)
|
- Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769)
|
||||||
|
71
imgui.cpp
71
imgui.cpp
@ -9142,23 +9142,15 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s
|
|||||||
if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX)
|
if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX)
|
||||||
v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio;
|
v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio;
|
||||||
|
|
||||||
if (g.ActiveIdIsJustActivated)
|
// Inputs accumulate into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
|
||||||
{
|
|
||||||
// Lock current value on click
|
|
||||||
g.DragCurrentValue = *v;
|
|
||||||
g.DragLastMouseDelta = ImVec2(0.f, 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f);
|
|
||||||
float adjust_delta = 0.0f;
|
float adjust_delta = 0.0f;
|
||||||
if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid())
|
if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f)
|
||||||
{
|
{
|
||||||
adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x;
|
adjust_delta = g.IO.MouseDelta.x;
|
||||||
if (g.IO.KeyAlt)
|
if (g.IO.KeyAlt)
|
||||||
adjust_delta *= 1.0f/100.0f;
|
adjust_delta *= 1.0f/100.0f;
|
||||||
if (g.IO.KeyShift)
|
if (g.IO.KeyShift)
|
||||||
adjust_delta *= 10.0f;
|
adjust_delta *= 10.0f;
|
||||||
g.DragLastMouseDelta.x = mouse_drag_delta.x;
|
|
||||||
}
|
}
|
||||||
if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||||
{
|
{
|
||||||
@ -9168,42 +9160,56 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s
|
|||||||
}
|
}
|
||||||
adjust_delta *= v_speed;
|
adjust_delta *= v_speed;
|
||||||
|
|
||||||
// Avoid applying the saturation 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
|
// Clear current value on activation
|
||||||
float v_cur = g.DragCurrentValue;
|
// 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.
|
||||||
if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f)))
|
bool is_just_activated = g.ActiveIdIsJustActivated;
|
||||||
adjust_delta = 0.0f;
|
bool is_already_past_limits_and_pushing_outward = (v_min < v_max) && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
|
||||||
|
if (is_just_activated || is_already_past_limits_and_pushing_outward)
|
||||||
|
{
|
||||||
|
g.DragCurrentAccum = 0.0f;
|
||||||
|
g.DragCurrentAccumDirty = false;
|
||||||
|
}
|
||||||
|
else if (adjust_delta != 0.0f)
|
||||||
|
{
|
||||||
|
g.DragCurrentAccum += adjust_delta;
|
||||||
|
g.DragCurrentAccumDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (fabsf(adjust_delta) > 0.0f)
|
bool value_changed = false;
|
||||||
|
if (g.DragCurrentAccumDirty)
|
||||||
{
|
{
|
||||||
if (fabsf(power - 1.0f) > 0.001f)
|
float v_cur = *v;
|
||||||
|
if (power != 1.0f && v_min != v_max)
|
||||||
{
|
{
|
||||||
// Power curve on both side of 0.0
|
// Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range
|
||||||
float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur;
|
IM_ASSERT(v_min != v_max); // When using a power curve the drag needs to have known bounds
|
||||||
float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f;
|
float v_old_norm_curved = powf((v_cur - v_min) / (v_max - v_min), 1.0f / power);
|
||||||
float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign);
|
float v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min));
|
||||||
float v1_abs = v1 >= 0.0f ? v1 : -v1;
|
v_cur = v_min + powf(ImSaturate(v_new_norm_curved), power) * (v_max - v_min);
|
||||||
float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line
|
v_cur = RoundScalarWithFormat(format, v_cur);
|
||||||
v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign
|
float v_cur_norm_curved = powf((v_cur - v_min) / (v_max - v_min), 1.0f / power);
|
||||||
|
g.DragCurrentAccum -= (v_cur_norm_curved - v_old_norm_curved); // Preserve remainder
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v_cur += adjust_delta;
|
// Offset + round to user desired precision
|
||||||
|
v_cur += g.DragCurrentAccum;
|
||||||
|
v_cur = RoundScalarWithFormat(format, v_cur);
|
||||||
|
g.DragCurrentAccum -= (v_cur - *v); // Preserve remainder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp
|
// Clamp
|
||||||
if (v_min < v_max)
|
if (*v != v_cur && v_min < v_max)
|
||||||
v_cur = ImClamp(v_cur, v_min, v_max);
|
v_cur = ImClamp(v_cur, v_min, v_max);
|
||||||
g.DragCurrentValue = v_cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round to user desired precision, then apply
|
// Apply result
|
||||||
bool value_changed = false;
|
|
||||||
v_cur = RoundScalarWithFormat(format, v_cur);
|
|
||||||
if (*v != v_cur)
|
if (*v != v_cur)
|
||||||
{
|
{
|
||||||
*v = v_cur;
|
*v = v_cur;
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
|
g.DragCurrentAccumDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
return value_changed;
|
return value_changed;
|
||||||
}
|
}
|
||||||
@ -9214,6 +9220,9 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f
|
|||||||
if (window->SkipItems)
|
if (window->SkipItems)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (power != 1.0f)
|
||||||
|
IM_ASSERT(v_min != v_max); // When using a power curve the drag needs to have known bounds
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
const ImGuiStyle& style = g.Style;
|
const ImGuiStyle& style = g.Style;
|
||||||
const ImGuiID id = window->GetID(label);
|
const ImGuiID id = window->GetID(label);
|
||||||
|
@ -668,8 +668,8 @@ struct ImGuiContext
|
|||||||
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||||
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
|
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
|
||||||
ImVec4 ColorPickerRef;
|
ImVec4 ColorPickerRef;
|
||||||
float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings
|
bool DragCurrentAccumDirty;
|
||||||
ImVec2 DragLastMouseDelta;
|
float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
|
||||||
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
|
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
|
||||||
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
|
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
|
||||||
int TooltipOverrideCount;
|
int TooltipOverrideCount;
|
||||||
@ -771,8 +771,8 @@ struct ImGuiContext
|
|||||||
|
|
||||||
ScalarAsInputTextId = 0;
|
ScalarAsInputTextId = 0;
|
||||||
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
||||||
DragCurrentValue = 0.0f;
|
DragCurrentAccumDirty = false;
|
||||||
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
|
DragCurrentAccum = 0.0f;
|
||||||
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||||
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
|
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
|
||||||
TooltipOverrideCount = 0;
|
TooltipOverrideCount = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user