X-Git-Url: https://git.blender.org/gitweb/gitweb.cgi/blender-staging.git/blobdiff_plain/a5152b7ca0d6d7f340b1955c0e8a15ba23fda336..b6a9a953bc6aa7d81921a796e8ce1123fdedefc7:/source/blender/editors/transform/transform.c diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ae383fcd6b2..1f219a699d2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -536,6 +536,12 @@ static void view_editmove(unsigned short UNUSED(event)) #define TFM_MODAL_AUTOIK_LEN_INC 22 #define TFM_MODAL_AUTOIK_LEN_DEC 23 +#define TFM_MODAL_EDGESLIDE_UP 24 +#define TFM_MODAL_EDGESLIDE_DOWN 25 + +#define TFM_WHEEL_DOWN_EVT TFM_MODAL_PROPSIZE_DOWN|TFM_MODAL_EDGESLIDE_DOWN +#define TFM_WHEEL_UP_EVT TFM_MODAL_PROPSIZE_UP|TFM_MODAL_EDGESLIDE_UP + /* called in transform_ops.c, on each regeneration of keymaps */ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf) { @@ -563,6 +569,8 @@ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf) {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""}, {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""}, {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""}, + {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, {0, NULL, 0, NULL, NULL}}; wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "Transform Modal Map"); @@ -595,8 +603,8 @@ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); - WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); - WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); + WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_WHEEL_UP_EVT); + WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_WHEEL_DOWN_EVT); WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC); WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC); @@ -617,7 +625,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm char axis; /* Initialize */ - switch(key_type) { + switch (key_type) { case XKEY: axis = 'X'; constraint_axis = CON_AXIS0; @@ -858,7 +866,7 @@ int transformEvent(TransInfo *t, wmEvent *event) removeSnapPoint(t); t->redraw |= TREDRAW_HARD; break; - case TFM_MODAL_PROPSIZE_UP: + case TFM_WHEEL_UP_EVT: if (t->flag & T_PROP_EDIT) { t->prop_size*= 1.1f; if (t->spacetype==SPACE_VIEW3D && t->persp != RV3D_ORTHO) @@ -867,7 +875,7 @@ int transformEvent(TransInfo *t, wmEvent *event) } t->redraw |= TREDRAW_HARD; break; - case TFM_MODAL_PROPSIZE_DOWN: + case TFM_WHEEL_DOWN_EVT: if (t->flag & T_PROP_EDIT) { t->prop_size*= 0.90909090f; calculatePropRatio(t); @@ -1138,9 +1146,11 @@ int calculateTransformCenter(bContext *C, int centerMode, float *cent3d, int *ce calculateCenter(t); - if(cent2d) + if (cent2d) { copy_v2_v2_int(cent2d, t->center2d); - if(cent3d) { + } + + if (cent3d) { // Copy center from constraint center. Transform center can be local copy_v3_v3(cent3d, t->con.center); } @@ -1387,6 +1397,7 @@ static void drawTransformView(const struct bContext *C, struct ARegion *UNUSED(a drawConstraint(t); drawPropCircle(C, t); drawSnapping(C, t); + drawNonPropEdge(C, t); } #if 0 @@ -1630,6 +1641,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_RESIZE: initResize(t); break; + case TFM_SKIN_RESIZE: + initSkinResize(t); + break; case TFM_TOSPHERE: initToSphere(t); break; @@ -2111,7 +2125,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT); bConstraintOb cob; bConstraint *con; - int dolimit = 0; + int do_limit = FALSE; /* Evaluate valid constraints */ for (con= td->con; con; con= con->next) { @@ -2133,9 +2147,9 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) continue; /* only do conversion if necessary, to preserve quats and eulers */ - if (!dolimit) { + if (do_limit == FALSE) { constraintob_from_transdata(&cob, td); - dolimit= 1; + do_limit = TRUE; } /* do space conversions */ @@ -2157,7 +2171,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) } } - if (dolimit) { + if (do_limit) { /* copy results from cob->matrix */ if (td->ext->rotOrder == ROT_MODE_QUAT) { /* quats */ @@ -2311,8 +2325,8 @@ int handleEventWarp(TransInfo *t, wmEvent *event) if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { // Use customData pointer to signal warp direction - if (t->customData == NULL) - t->customData = (void*)1; + if (t->customData == NULL) + t->customData = (void *)1; else t->customData = NULL; @@ -2451,7 +2465,7 @@ int handleEventShear(TransInfo *t, wmEvent *event) if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { // Use customData pointer to signal Shear direction - if (t->customData == NULL) { + if (t->customData == NULL) { initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); t->customData = (void*)1; } @@ -2701,7 +2715,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) constraintSizeLim(t, td); } - + /* For individual element center, Editmode need to use iloc */ if (t->flag & T_POINTS) sub_v3_v3v3(vec, td->iloc, center); @@ -2799,6 +2813,96 @@ int Resize(TransInfo *t, const int mval[2]) return 1; } +/* ************************** SKIN *************************** */ + +void initSkinResize(TransInfo *t) +{ + t->mode = TFM_SKIN_RESIZE; + t->transform = SkinResize; + + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); + + t->flag |= T_NULL_ONE; + t->num.flag |= NUM_NULL_ONE; + t->num.flag |= NUM_AFFECT_ALL; + if (!t->obedit) { + t->flag |= T_NO_ZERO; + t->num.flag |= NUM_NO_ZERO; + } + + t->idx_max = 2; + t->num.idx_max = 2; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; +} + +int SkinResize(TransInfo *t, const int UNUSED(mval[2])) +{ + TransData *td; + float size[3], mat[3][3]; + float ratio; + int i; + char str[200]; + + ratio = t->values[0]; + size[0] = size[1] = size[2] = ratio; + + snapGrid(t, size); + + if (hasNumInput(&t->num)) { + applyNumInput(&t->num, size); + constraintNumInput(t, size); + } + + applySnapping(t, size); + + if (t->flag & T_AUTOVALUES) { + copy_v3_v3(size, t->auto_values); + } + + copy_v3_v3(t->values, size); + + size_to_mat3(mat, size); + + headerResize(t, size, str); + + for (i = 0, td = t->data; i < t->total; i++, td++) { + float tmat[3][3], smat[3][3]; + float fsize[3]; + + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (t->flag & T_EDIT) { + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); + } + else { + copy_m3_m3(tmat, mat); + } + + if (t->con.applySize) { + t->con.applySize(t, NULL, tmat); + } + + mat3_to_size(fsize, tmat); + td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); + td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + /* ************************** TOSPHERE *************************** */ void initToSphere(TransInfo *t) @@ -3096,7 +3200,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* rotation */ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself /* euler or quaternion? */ - if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { + if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); mat3_to_quat(quat, fmat); // Actual transform @@ -4373,6 +4477,41 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, return NULL; } +static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const float mval[2]) +{ + TransDataSlideVert *sv = sld->sv; + + if (sld->totsv > 0) { + int i = 0; + + float v_proj[3]; + float dist = 0; + float min_dist = FLT_MAX; + + float up_p[3]; + float dw_p[3]; + + for (i = 0; i < sld->totsv; i++, sv++) { + /* Set length */ + add_v3_v3v3(up_p, sv->origvert.co, sv->upvec); + add_v3_v3v3(dw_p, sv->origvert.co, sv->downvec); + sv->edge_len = len_v3v3(dw_p, up_p); + + mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); + project_float_noclip(t->ar, v_proj, v_proj); + + dist = len_squared_v2v2(mval, v_proj); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; + } + } + } + else { + sld->curr_sv_index = 0; + } +} + static int createSlideVerts(TransInfo *t) { Mesh *me = t->obedit->data; @@ -4390,10 +4529,15 @@ static int createSlideVerts(TransInfo *t) RegionView3D *rv3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */ ARegion *ar = t->ar; float projectMat[4][4]; + float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f}; float vec[3], vec2[3], lastvec[3] /*, size, dis=0.0, z */ /* UNUSED */; int numsel, i, j; + sld->is_proportional = TRUE; + sld->curr_sv_index = 0; + sld->flipped_vtx = FALSE; + if (!v3d) { /* ok, let's try to survive this */ unit_m4(projectMat); @@ -4656,7 +4800,10 @@ static int createSlideVerts(TransInfo *t) BLI_smallhash_insert(&sld->vhash, (uintptr_t)sv_array->v, sv_array); } - + + calcNonProportionalEdgeSlide(t, sld, mval); + + sld->origfaces_init = TRUE; sld->em = em; @@ -4665,7 +4812,7 @@ static int createSlideVerts(TransInfo *t) /*dir holds a vector along edge loop*/ copy_v3_v3(end, dir); - mul_v3_fl(end, 0.5); + mul_v3_fl(end, 0.5f); sld->start[0] = t->mval[0] + start[0]; sld->start[1] = t->mval[1] + start[1]; @@ -4711,7 +4858,7 @@ void projectSVData(TransInfo *t, int final) /* BMESH_TODO, this interpolates between vertex/loops which are not moved * (are only apart of a face attached to a slide vert), couldn't we iterate BM_LOOPS_OF_VERT - * here and only iterpolate those? */ + * here and only interpolate those? */ BM_ITER_ELEM (f, &fiter, sv->v, BM_FACES_OF_VERT) { BMIter liter; BMLoop *l; @@ -4890,7 +5037,8 @@ void initEdgeSlide(TransInfo *t) t->mode = TFM_EDGE_SLIDE; t->transform = EdgeSlide; - + t->handleEvent = handleEventEdgeSlide; + if (!createSlideVerts(t)) { t->state= TRANS_CANCEL; return; @@ -4918,6 +5066,122 @@ void initEdgeSlide(TransInfo *t) t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; } +int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) +{ + if (t->flag & TFM_EDGE_SLIDE) { + SlideData *sld = t->customData; + + if (sld) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + sld->is_proportional = !sld->is_proportional; + return 1; + } + break; + case FKEY: { + if (event->val == KM_PRESS) { + if (sld->is_proportional == FALSE) { + sld->flipped_vtx = !sld->flipped_vtx; + } + return 1; + } + break; + } + case EVT_MODAL_MAP: { + switch (event->val) { + case TFM_WHEEL_DOWN_EVT: { + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + break; + } + case TFM_WHEEL_UP_EVT: { + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + break; + } + } + } + default: + break; + } + } + } + return 0; +} + +void drawNonPropEdge(const struct bContext *C, TransInfo *t) +{ + if (t->flag & TFM_EDGE_SLIDE) { + SlideData *sld = (SlideData *)t->customData; + /* Non-Prop mode */ + if (sld && sld->is_proportional == FALSE) { + View3D *v3d = CTX_wm_view3d(C); + float marker[3]; + float v1[3], v2[3]; + float interp_v; + TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5; + const float guide_size = ctrl_size - 0.5f; + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + const int alpha_shade = -30; + + add_v3_v3v3(v1, curr_sv->origvert.co, curr_sv->upvec); + add_v3_v3v3(v2, curr_sv->origvert.co, curr_sv->downvec); + + interp_v = (sld->perc + 1.0f) / 2.0f; + interp_v3_v3v3(marker, v2, v1, interp_v); + + if (v3d && v3d->zbuf) + glDisable(GL_DEPTH_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); + glPushMatrix(); + + glMultMatrixf(t->obedit->obmat); + + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + glVertex3fv(curr_sv->up->co); + glVertex3fv(curr_sv->origvert.co); + glVertex3fv(curr_sv->down->co); + glVertex3fv(curr_sv->origvert.co); + bglEnd(); + + + UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + glPointSize(ctrl_size); + if (sld->flipped_vtx) { + bglBegin(GL_POINTS); + bglVertex3fv(curr_sv->down->co); + bglEnd(); + } + else { + bglBegin(GL_POINTS); + bglVertex3fv(curr_sv->up->co); + bglEnd(); + } + + UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + glPointSize(guide_size); + bglBegin(GL_POINTS); + bglVertex3fv(marker); + bglEnd(); + + + glPopMatrix(); + glPopAttrib(); + + glDisable(GL_BLEND); + + if (v3d && v3d->zbuf) + glEnable(GL_DEPTH_TEST); + } + } +} + static int doEdgeSlide(TransInfo *t, float perc) { SlideData *sld = t->customData; @@ -4929,6 +5193,30 @@ static int doEdgeSlide(TransInfo *t, float perc) sv = svlist; for (i=0; itotsv; i++, sv++) { + if (sld->is_proportional == FALSE) { + TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + float cur_sel = curr_sv->edge_len; + float cur_sv = sv->edge_len; + float extd = 0.0f; + float recip_cur_sv = 0.0f; + + if (cur_sel == 0.0f) cur_sel = 1.0f; + if (cur_sv == 0.0f) cur_sv = 1.0f; + + recip_cur_sv = 1.0f / cur_sv; + + if (!sld->flipped_vtx) { + extd = (cur_sv - cur_sel) * recip_cur_sv; + } + else { + extd = (cur_sel - cur_sv) * recip_cur_sv; + } + + extd += (sld->perc * cur_sel) * recip_cur_sv; + CLAMP(extd, -1.0f, 1.0f); + perc = extd; + } + if (perc > 0.0f) { copy_v3_v3(vec, sv->upvec); mul_v3_fl(vec, perc); @@ -4948,8 +5236,11 @@ static int doEdgeSlide(TransInfo *t, float perc) int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[50]; + char str[128]; float final; + SlideData *sld = t->customData; + int flipped = sld->flipped_vtx; + int is_proportional = sld->is_proportional; final = t->values[0]; @@ -4965,10 +5256,12 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Edge Slide: %s", &c[0]); + BLI_snprintf(str, sizeof(str), "Edge Slide: %s (E)ven: %s, (F)lipped: %s", + &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF" ); } else { - sprintf(str, "Edge Slide: %.2f", final); + BLI_snprintf(str, sizeof(str), "Edge Slide: %.2f (E)ven: %s, (F)lipped: %s", + final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF" ); } CLAMP(final, -1.0f, 1.0f); @@ -5438,10 +5731,10 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, /* snap key to nearest frame? */ if (autosnap == SACTSNAP_FRAME) { -#if 0 /* 'doTime' disabled for now */ +#if 0 /* 'do_time' disabled for now */ const Scene *scene= t->scene; - const short doTime= 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behavior given the option's label, hence disabled + const short do_time= 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behavior given the option's label, hence disabled const double secf= FPS; #endif double val; @@ -5452,16 +5745,16 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, else val= *(td->val); -#if 0 /* 'doTime' disabled for now */ +#if 0 /* 'do_time' disabled for now */ /* do the snapping to nearest frame/second */ - if (doTime) { + if (do_time) { val= (float)(floor((val/secf) + 0.5f) * secf); } else #endif { - val= floorf(val+0.5f); + val = floor(val + 0.5); } /* convert frame out of nla-action time */ @@ -5540,19 +5833,19 @@ static void headerTimeTranslate(TransInfo *t, char *str) else { const Scene *scene = t->scene; const short autosnap= getAnimEdit_SnapMode(t); - const short doTime = getAnimEdit_DrawTime(t); + const short do_time = getAnimEdit_DrawTime(t); const double secf= FPS; float val = t->values[0]; /* apply snapping + frame->seconds conversions */ if (autosnap == SACTSNAP_STEP) { - if (doTime) - val= floorf((double)val/secf + 0.5f); + if (do_time) + val= floorf((double)val / secf + 0.5); else val= floorf(val + 0.5f); } else { - if (doTime) + if (do_time) val= (float)((double)val / secf); } @@ -5572,7 +5865,7 @@ static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) Scene *scene = t->scene; int i; - const short doTime= getAnimEdit_DrawTime(t); + const short do_time= getAnimEdit_DrawTime(t); const double secf= FPS; const short autosnap= getAnimEdit_SnapMode(t); @@ -5594,10 +5887,10 @@ static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) deltax = t->values[0]; if (autosnap == SACTSNAP_STEP) { - if (doTime) - deltax= (float)(floor((deltax/secf) + 0.5f) * secf); + if (do_time) + deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf); else - deltax= (float)(floor(deltax + 0.5f)); + deltax = (float)(floor(deltax + 0.5f)); } val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); @@ -5608,10 +5901,10 @@ static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) deltax = val = t->values[0]; if (autosnap == SACTSNAP_STEP) { - if (doTime) - val= (float)(floor((deltax/secf) + 0.5f) * secf); + if (do_time) + val = (float)(floor(((double)deltax / secf) + 0.5) * secf); else - val= (float)(floor(val + 0.5f)); + val = (float)(floor(val + 0.5f)); } *(td->val) = td->ival + val; @@ -5846,7 +6139,7 @@ static void applyTimeScale(TransInfo *t) int i; const short autosnap= getAnimEdit_SnapMode(t); - const short doTime= getAnimEdit_DrawTime(t); + const short do_time= getAnimEdit_DrawTime(t); const double secf= FPS; @@ -5860,10 +6153,10 @@ static void applyTimeScale(TransInfo *t) float fac= t->values[0]; if (autosnap == SACTSNAP_STEP) { - if (doTime) - fac= (float)(floor(fac/secf + 0.5f) * secf); + if (do_time) + fac = (float)(floor((double)fac / secf + 0.5) * secf); else - fac= (float)(floor(fac + 0.5f)); + fac = (float)(floor(fac + 0.5f)); } /* check if any need to apply nla-mapping */ @@ -5871,9 +6164,7 @@ static void applyTimeScale(TransInfo *t) startx= BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); /* now, calculate the new value */ - *(td->val) = td->ival - startx; - *(td->val) *= fac; - *(td->val) += startx; + *(td->val) = ((td->ival - startx) * fac) + startx; /* apply nearest snapping */ doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);