Fix T68130: Over sensitive number button dragging

When continuous grab, cursor motion was mapped to the min/max.
This caused problems when int/float max values were used.

Now the range is clamped by a value derived from the click-step
so dragging numbers never increases it to an impractically large value.
This commit is contained in:
Campbell Barton 2019-11-05 12:07:33 +11:00
parent 95a60fe84d
commit 490d5bb750
Notes: blender-bot 2023-02-14 10:18:56 +01:00
Referenced by issue #68130, Skyrocketing (infm) values when disabling Continuous Drag
1 changed files with 93 additions and 17 deletions

View File

@ -101,6 +101,19 @@
#define UI_MAX_PASSWORD_STR 128
/**
* When #USER_CONTINUOUS_MOUSE is disabled or tablet input is used,
* Use this as a maximum soft range for mapping cursor motion to the value.
* Otherwise min/max of #FLT_MAX, #INT_MAX cause small adjustments to jump to large numbers.
*
* This is needed for values such as location & dimensions which don't have a meaningful min/max,
* Instead of mapping cursor motion to the min/max, map the motion to the click-step.
*
* This value is multiplied by the click step to calculate a range to clamp the soft-range by.
* See: T68130
*/
#define UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX 1000
/* proto */
static int ui_do_but_EXIT(bContext *C,
uiBut *but,
@ -339,6 +352,10 @@ typedef struct uiHandleButtonData {
float dragf, dragfstart;
CBData *dragcbd;
/** Soft min/max with #UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX applied. */
float drag_map_soft_min;
float drag_map_soft_max;
#ifdef USE_CONT_MOUSE_CORRECT
/* when ungrabbing buttons which are #ui_but_is_cursor_warp(),
* we may want to position them.
@ -3746,8 +3763,59 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
softmax = but->softmax;
softrange = softmax - softmin;
if ((but->type == UI_BTYPE_NUM) && (ui_but_is_cursor_warp(but) == false)) {
/* Use a minimum so we have a predictable range,
* otherwise some float buttons get a large range. */
const float value_step_float_min = 0.1f;
const bool is_float = ui_but_is_float(but);
const double value_step = is_float ? (double)(but->a1 * UI_PRECISION_FLOAT_SCALE) :
(int)but->a1;
const float drag_map_softrange_max = UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX * UI_DPI_FAC;
const float softrange_max = min_ff(
softrange,
2 * (is_float ? min_ff(value_step, value_step_float_min) *
(drag_map_softrange_max / value_step_float_min) :
drag_map_softrange_max));
if (softrange > softrange_max) {
/* Center around the value, keeping in the real soft min/max range. */
softmin = data->origvalue - (softrange_max / 2);
softmax = data->origvalue + (softrange_max / 2);
if (!isfinite(softmin)) {
softmin = (data->origvalue > 0.0f ? FLT_MAX : -FLT_MAX);
}
if (!isfinite(softmax)) {
softmax = (data->origvalue > 0.0f ? FLT_MAX : -FLT_MAX);
}
if (softmin < but->softmin) {
softmin = but->softmin;
softmax = softmin + softrange_max;
}
else if (softmax > but->softmax) {
softmax = but->softmax;
softmin = softmax - softrange_max;
}
/* Can happen at extreme values. */
if (UNLIKELY(softmin == softmax)) {
if (data->origvalue > 0.0) {
softmin = nextafterf(softmin, -FLT_MAX);
}
else {
softmax = nextafterf(softmax, FLT_MAX);
}
}
softrange = softmax - softmin;
}
}
data->dragfstart = (softrange == 0.0f) ? 0.0f : ((float)data->value - softmin) / softrange;
data->dragf = data->dragfstart;
data->drag_map_soft_min = softmin;
data->drag_map_soft_max = softmax;
}
data->dragchange = false;
@ -4382,17 +4450,14 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
/* var names match ui_numedit_but_NUM */
static float ui_numedit_apply_snapf(uiBut *but,
float tempf,
float softmin,
float softmax,
float softrange,
const enum eSnapType snap)
static float ui_numedit_apply_snapf(
uiBut *but, float tempf, float softmin, float softmax, const enum eSnapType snap)
{
if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) {
/* pass */
}
else {
float softrange = softmax - softmin;
float fac = 1.0f;
if (ui_but_is_unit(but)) {
@ -4493,7 +4558,7 @@ static bool ui_numedit_but_NUM(uiBut *but,
const enum eSnapType snap,
float fac)
{
float deler, tempf, softmin, softmax, softrange;
float deler, tempf;
int lvalue, temp;
bool changed = false;
const bool is_float = ui_but_is_float(but);
@ -4503,17 +4568,17 @@ static bool ui_numedit_but_NUM(uiBut *but,
return changed;
}
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
if (ui_but_is_cursor_warp(but)) {
const float softmin = but->softmin;
const float softmax = but->softmax;
const float softrange = softmax - softmin;
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if (is_float) {
fac *= 0.01f * but->a1;
tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, snap);
#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
if (tempf < softmin) {
@ -4571,6 +4636,11 @@ static bool ui_numedit_but_NUM(uiBut *but,
data->draglastx = mx;
}
else {
/* Use 'but->softmin', 'but->softmax' when clamping values. */
const float softmin = data->drag_map_soft_min;
const float softmax = data->drag_map_soft_max;
const float softrange = softmax - softmin;
float non_linear_range_limit;
float non_linear_pixel_map;
float non_linear_scale;
@ -4616,16 +4686,22 @@ static bool ui_numedit_but_NUM(uiBut *but,
data->dragf += (((float)(mx - data->draglastx)) / deler) * non_linear_scale;
CLAMP(data->dragf, 0.0f, 1.0f);
if (but->softmin == softmin) {
CLAMP_MIN(data->dragf, 0.0f);
}
if (but->softmax == softmax) {
CLAMP_MAX(data->dragf, 1.0f);
}
data->draglastx = mx;
tempf = (softmin + data->dragf * softrange);
if (!is_float) {
temp = round_fl_to_int(tempf);
temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
temp = ui_numedit_apply_snap(temp, but->softmin, but->softmax, snap);
CLAMP(temp, softmin, softmax);
CLAMP(temp, but->softmin, but->softmax);
lvalue = (int)data->value;
if (temp != lvalue) {
@ -4636,9 +4712,9 @@ static bool ui_numedit_but_NUM(uiBut *but,
}
else {
temp = 0;
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
tempf = ui_numedit_apply_snapf(but, tempf, but->softmin, but->softmax, snap);
CLAMP(tempf, softmin, softmax);
CLAMP(tempf, but->softmin, but->softmax);
if (tempf != (float)data->value) {
data->dragchange = true;