Transform: Support storing virtual cursor location

Grabbing now doesn't 'jump' when shift is released (matching rotation modes).

This simplifies most logic for transform input,
where mouse input callbacks can choose to use the 'virtual' cursor,
which accounts for precision when shift is held.
This commit is contained in:
Campbell Barton 2015-10-30 17:31:07 +11:00
parent d2af140151
commit e6abc3ad57
3 changed files with 95 additions and 113 deletions

View File

@ -313,7 +313,7 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
r_vec[2] = 0.0f;
}
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
{
if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
if (t->options & CTX_PAINT_CURVE) {
@ -7605,12 +7605,17 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
float fac = 0.1f;
/* XXX, disable precission for now,
* this isn't even accessible by the user */
#if 0
if (t->mouse.precision) {
/* calculate ratio for shiftkey pos, and for total, and blend these for precision */
time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time);
}
else {
else
#endif
{
time = (float)(t->center2d[0] - mval[0]) * fac;
}

View File

@ -326,15 +326,29 @@ typedef struct TransData {
} TransData;
typedef struct MouseInput {
void (*apply)(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
void (*post)(struct TransInfo *t, float values[3]);
int imval[2]; /* initial mouse position */
bool precision;
int precision_mval[2]; /* mouse position when precision key was pressed */
float precision_factor;
float center[2];
float factor;
void *data; /* additional data, if needed by the particular function */
/**
* Use virtual cursor, which takes precission into account
* keeping track of the cursors 'virtual' location,
* to avoid jumping values when its toggled.
*
* This works well for scaling drag motion,
* but not for rotating around a point (rotaton needs its own custom accumulator)
*/
bool use_virtual_mval;
struct {
double prev[2];
double accum[2];
} virtual_mval;
} MouseInput;
typedef struct TransInfo {
@ -549,7 +563,7 @@ int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy);
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy);
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag);
void projectIntView(TransInfo *t, const float vec[3], int adr[2]);
void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag);

View File

@ -39,54 +39,26 @@
#include "MEM_guardedalloc.h"
struct InputTrackBall_Data {
float value_accum[2];
float value_prev[2];
};
/* ************************** INPUT FROM MOUSE *************************** */
static void InputVector(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
float vec[3], dvec[3];
if (mi->precision) {
/* calculate the main translation and the precise one separate */
convertViewVec(t, dvec, (mval[0] - mi->precision_mval[0]), (mval[1] - mi->precision_mval[1]));
mul_v3_fl(dvec, 0.1f);
convertViewVec(t, vec, (mi->precision_mval[0] - t->mouse.imval[0]), (mi->precision_mval[1] - t->mouse.imval[1]));
add_v3_v3v3(output, vec, dvec);
}
else {
convertViewVec(t, output, (mval[0] - t->mouse.imval[0]), (mval[1] - t->mouse.imval[1]));
}
convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
}
static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
float ratio, precise_ratio, dx, dy;
if (mi->precision) {
/* calculate ratio for shiftkey pos, and for total, and blend these for precision */
dx = (float)(mi->center[0] - mi->precision_mval[0]);
dy = (float)(mi->center[1] - mi->precision_mval[1]);
ratio = hypotf(dx, dy);
double dx, dy;
float ratio;
dx = (float)(mi->center[0] - mval[0]);
dy = (float)(mi->center[1] - mval[1]);
precise_ratio = hypotf(dx, dy);
ratio = (ratio + (precise_ratio - ratio) / 10.0f) / mi->factor;
}
else {
dx = (float)(mi->center[0] - mval[0]);
dy = (float)(mi->center[1] - mval[1]);
ratio = hypotf(dx, dy) / mi->factor;
}
dx = (mi->center[0] - mval[0]);
dy = (mi->center[1] - mval[1]);
ratio = hypot(dx, dy) / mi->factor;
output[0] = ratio;
}
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputSpring(t, mi, mval, output);
@ -99,51 +71,29 @@ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const int mval[2], flo
}
}
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputSpring(t, mi, mval, output);
output[0] -= 1.0f;
}
static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
struct InputTrackBall_Data *data = mi->data;
float dxy[2];
float dxy_accum[2];
output[0] = (float)(mi->imval[1] - mval[1]);
output[1] = (float)(mval[0] - mi->imval[0]);
dxy[0] = (mi->imval[1] - mval[1]);
dxy[1] = (mval[0] - mi->imval[0]);
sub_v2_v2v2(dxy_accum, dxy, data->value_prev);
add_v2_v2(data->value_prev, dxy_accum);
if (mi->precision) {
mul_v2_fl(dxy_accum, 1.0f / 30.0f);
}
add_v2_v2(data->value_accum, dxy_accum);
mul_v2_v2fl(output, data->value_accum, mi->factor);
output[0] *= mi->factor;
output[1] *= mi->factor;
}
static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputHorizontalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
{
float x, pad;
const float pad = t->ar->winx / 10;
pad = t->ar->winx / 10;
if (mi->precision) {
/* deal with Shift key by adding motion / 10 to motion before shift press */
x = mi->precision_mval[0] + (float)(mval[0] - mi->precision_mval[0]) / 10.0f;
}
else {
x = mval[0];
}
output[0] = (x - pad) / (t->ar->winx - 2 * pad);
output[0] = (mval[0] - pad) / (t->ar->winx - 2 * pad);
}
static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
float vec[3];
@ -153,24 +103,14 @@ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const int mval
output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
}
static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputVerticalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
{
float y, pad;
const float pad = t->ar->winy / 10;
pad = t->ar->winy / 10;
if (mi->precision) {
/* deal with Shift key by adding motion / 10 to motion before shift press */
y = mi->precision_mval[1] + (float)(mval[1] - mi->precision_mval[1]) / 10.0f;
}
else {
y = mval[0];
}
output[0] = (y - pad) / (t->ar->winy - 2 * pad);
output[0] = (mval[1] - pad) / (t->ar->winy - 2 * pad);
}
static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
float vec[3];
@ -194,7 +134,7 @@ void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int mval_start[
data[3] = mval_end[1];
}
static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
double length;
double distance;
@ -202,38 +142,28 @@ static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const int
const int *data = mi->data;
if (data) {
int mdx, mdy;
dx = data[2] - data[0];
dy = data[3] - data[1];
length = hypot(dx, dy);
if (mi->precision) {
/* deal with Shift key by adding motion / 10 to motion before shift press */
int mdx, mdy;
mdx = (mi->precision_mval[0] + (float)(mval[0] - mi->precision_mval[0]) / 10.0f) - data[2];
mdy = (mi->precision_mval[1] + (float)(mval[1] - mi->precision_mval[1]) / 10.0f) - data[3];
distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
}
else {
int mdx, mdy;
mdx = mval[0] - data[2];
mdy = mval[1] - data[3];
mdx = mval[0] - data[2];
mdy = mval[1] - data[3];
distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
}
distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
output[0] = (length != 0.0) ? (double)(distance / length) : 0.0;
}
}
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputCustomRatioFlip(t, mi, mval, output);
output[0] = -output[0];
}
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
double dx2 = mval[0] - mi->center[0];
double dy2 = mval[1] - mi->center[1];
@ -281,7 +211,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
}
if (mi->precision) {
dphi = dphi / 30.0f;
dphi = dphi * mi->precision_factor;
}
/* if no delta angle, don't update initial position */
@ -295,7 +225,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
output[0] = *angle;
}
static void InputAngleSpring(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
float toutput[3];
@ -334,6 +264,9 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
/* incase we allocate a new value */
void *mi_data_prev = mi->data;
mi->use_virtual_mval = true;
mi->precision_factor = 1.0f / 10.0f;
switch (mode) {
case INPUT_VECTOR:
mi->apply = InputVector;
@ -355,20 +288,23 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
t->helpline = HLP_SPRING;
break;
case INPUT_ANGLE:
mi->use_virtual_mval = false;
mi->precision_factor = 1.0f / 30.0f;
mi->data = MEM_callocN(sizeof(double), "angle accumulator");
mi->apply = InputAngle;
t->helpline = HLP_ANGLE;
break;
case INPUT_ANGLE_SPRING:
mi->use_virtual_mval = false;
calcSpringFactor(mi);
mi->data = MEM_callocN(sizeof(double), "angle accumulator");
mi->apply = InputAngleSpring;
t->helpline = HLP_ANGLE;
break;
case INPUT_TRACKBALL:
mi->precision_factor = 1.0f / 30.0f;
/* factor has to become setting or so */
mi->factor = 0.01f;
mi->data = MEM_callocN(sizeof(struct InputTrackBall_Data), "angle accumulator");
mi->apply = InputTrackBall;
t->helpline = HLP_TRACKBALL;
break;
@ -420,8 +356,37 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val
void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
{
double mval_db[2];
if (mi->use_virtual_mval) {
/* update accumulator */
double mval_delta[2];
mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
mi->virtual_mval.prev[0] += mval_delta[0];
mi->virtual_mval.prev[1] += mval_delta[1];
if (mi->precision) {
mval_delta[0] *= mi->precision_factor;
mval_delta[1] *= mi->precision_factor;
}
mi->virtual_mval.accum[0] += mval_delta[0];
mi->virtual_mval.accum[1] += mval_delta[1];
mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
}
else {
mval_db[0] = mval[0];
mval_db[1] = mval[1];
}
if (mi->apply != NULL) {
mi->apply(t, mi, mval, output);
mi->apply(t, mi, mval_db, output);
}
if (mi->post) {
@ -438,9 +403,7 @@ eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
case RIGHTSHIFTKEY:
if (event->val == KM_PRESS) {
t->modifiers |= MOD_PRECISION;
/* shift is modifier for higher precision transform
* store the mouse position where the normal movement ended */
copy_v2_v2_int(mi->precision_mval, event->mval);
/* shift is modifier for higher precision transforn */
mi->precision = 1;
redraw = TREDRAW_HARD;
}