diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 2582920b697..ecc4ec248ad 100755 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -53,6 +53,7 @@ #define TFM_BONESIZE 15 #define TFM_BONE_ENVELOPE 16 #define TFM_CURVE_SHRINKFATTEN 17 +#define TFM_BONE_ROLL 18 /* TRANSFORM CONTEXTS */ #define CTX_NONE 0 diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index a8c9b9ba662..c9598f8e00c 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3530,6 +3530,9 @@ static void do_view3d_edit_armaturemenu(void *arg, int event) case 13: /* flip left and right names */ armature_flip_names(); break; + case 14: /* interactively set bone roll */ + initTransform(TFM_BONE_ROLL, CTX_NONE); + Transform(); } allqueue(REDRAWVIEW3D, 0); } @@ -3551,6 +3554,7 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused) uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Bone Roll Angle|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Bone Roll Angle|Ctrl N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index db8c0781f6a..651d2d72131 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1876,10 +1876,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) CutEdgeloop(1); BIF_undo_push("Cut Edgeloop"); } - //else if (G.obedit->type==OB_ARMATURE) { - // initTransform(TFM_BONE_ROLL, CTX_NONE); - // Transform(); - //} + else if (G.obedit->type==OB_ARMATURE) { + initTransform(TFM_BONE_ROLL, CTX_NONE); + Transform(); + } } else if((G.qual==0)) { initTransform(TFM_ROTATION, CTX_NONE); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 36bbc693c2d..59564ec83dd 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -809,6 +809,9 @@ void initTransform(int mode, int context) { case TFM_BONE_ENVELOPE: initBoneEnvelope(&Trans); break; + case TFM_BONE_ROLL: + initBoneRoll(&Trans); + break; } } @@ -2588,6 +2591,284 @@ int Crease(TransInfo *t, short mval[2]) return 1; } +/* ******************** EditBone (B-bone) width scaling *************** */ + +void initBoneSize(TransInfo *t) +{ + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + t->transform = BoneSize; + t->fac = (float)sqrt( ( + ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1])) + + + ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0])) + ) ); + + if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf +} + +static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) +{ + float tmat[3][3], smat[3][3], oldy; + float sizemat[3][3]; + + Mat3MulMat3(smat, mat, td->mtx); + Mat3MulMat3(tmat, td->smtx, smat); + + if (t->con.applySize) { + t->con.applySize(t, td, tmat); + } + + /* we've tucked the scale in loc */ + oldy= td->iloc[1]; + SizeToMat3(td->iloc, sizemat); + Mat3MulMat3(tmat, tmat, sizemat); + Mat3ToSize(tmat, td->loc); + td->loc[1]= oldy; +} + +int BoneSize(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + float size[3], mat[3][3]; + float ratio; + int i; + char str[50]; + + /* for manipulator, center handle, the scaling can't be done relative to center */ + if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) { + ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f; + } + else { + + if(t->flag & T_SHIFT_MOD) { + /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ + float dx= (float)(t->center2d[0] - t->shiftmval[0]); + float dy= (float)(t->center2d[1] - t->shiftmval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + + dx= (float)(t->center2d[0] - mval[0]); + dy= (float)(t->center2d[1] - mval[1]); + ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio); + + } + else { + float dx= (float)(t->center2d[0] - mval[0]); + float dy= (float)(t->center2d[1] - mval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + } + + /* flip scale, but not for manipulator center handle */ + if ((t->center2d[0] - mval[0]) * (t->center2d[0] - t->imval[0]) + + (t->center2d[1] - mval[1]) * (t->center2d[1] - t->imval[1]) < 0) + ratio *= -1.0f; + } + + size[0] = size[1] = size[2] = ratio; + + snapGrid(t, size); + + if (hasNumInput(&t->num)) { + applyNumInput(&t->num, size); + constraintNumInput(t, size); + } + + SizeToMat3(size, mat); + + if (t->con.applySize) { + t->con.applySize(t, NULL, mat); + } + + Mat3CpyMat3(t->mat, mat); // used in manipulator + + headerResize(t, size, str); + + for(i = 0 ; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + ElementBoneSize(t, td, mat); + } + + recalcData(t); + + headerprint(str); + + viewRedrawForce(t); + + if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); + + return 1; +} + + +/* ******************** EditBone envelope *************** */ + +void initBoneEnvelope(TransInfo *t) +{ + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + t->transform = BoneEnvelope; + t->fac = (float)sqrt( ( + ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1])) + + + ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0])) + ) ); + + if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf +} + +int BoneEnvelope(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + float ratio; + int i; + char str[50]; + + if(t->flag & T_SHIFT_MOD) { + /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ + float dx= (float)(t->center2d[0] - t->shiftmval[0]); + float dy= (float)(t->center2d[1] - t->shiftmval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + + dx= (float)(t->center2d[0] - mval[0]); + dy= (float)(t->center2d[1] - mval[1]); + ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio); + + } + else { + float dx= (float)(t->center2d[0] - mval[0]); + float dy= (float)(t->center2d[1] - mval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + } + + snapGrid(t, &ratio); + + applyNumInput(&t->num, &ratio); + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[20]; + + outputNumInput(&(t->num), c); + sprintf(str, "Envelope: %s", c); + } + else { + sprintf(str, "Envelope: %3f", ratio); + } + + for(i = 0 ; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if(td->val) *td->val= td->ival*ratio; + } + + recalcData(t); + + headerprint(str); + + force_draw(0); + + if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); + + return 1; +} + + +/* ******************** EditBone roll *************** */ + +void initBoneRoll(TransInfo *t) +{ + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = (float)((5.0/180)*M_PI); + t->snap[2] = t->snap[1] * 0.2f; + + t->fac = 0.0f; + + t->transform = BoneRoll; +} + +int BoneRoll(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + int i; + char str[50]; + + float final; + + int dx2 = t->center2d[0] - mval[0]; + int dy2 = t->center2d[1] - mval[1]; + double B = sqrt(dx2*dx2+dy2*dy2); + + int dx1 = t->center2d[0] - t->imval[0]; + int dy1 = t->center2d[1] - t->imval[1]; + double A = sqrt(dx1*dx1+dy1*dy1); + + int dx3 = mval[0] - t->imval[0]; + int dy3 = mval[1] - t->imval[1]; + /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */ + double deler= ((double)((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3) )) + / (2.0 * (A*B?A*B:1.0)); + /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */ + + float dphi; + + dphi = saacos((float)deler); + if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; + + if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f; + else t->fac += dphi; + + final = t->fac; + + snapGrid(t, &final); + + t->imval[0] = mval[0]; + t->imval[1] = mval[1]; + + if (hasNumInput(&t->num)) { + char c[20]; + + applyNumInput(&t->num, &final); + + outputNumInput(&(t->num), c); + + sprintf(str, "Roll: %s", &c[0]); + + final *= (float)(M_PI / 180.0); + } + else { + sprintf(str, "Roll: %.2f", 180.0*final/M_PI); + } + + /* set roll values */ + for (i = 0; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + *(td->val) = td->ival - final; + } + + recalcData(t); + + headerprint(str); + + viewRedrawForce(t); + + if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); + + return 1; +} + /* ************************** MIRROR *************************** */ void Mirror(short mode) @@ -2687,196 +2968,6 @@ void Mirror(short mode) viewRedrawPost(&Trans); } -/* ******************** EditBone (B-bone) width scaling *************** */ - -static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) -{ - float tmat[3][3], smat[3][3], oldy; - float sizemat[3][3]; - - Mat3MulMat3(smat, mat, td->mtx); - Mat3MulMat3(tmat, td->smtx, smat); - - if (t->con.applySize) { - t->con.applySize(t, td, tmat); - } - - /* we've tucked the scale in loc */ - oldy= td->iloc[1]; - SizeToMat3(td->iloc, sizemat); - Mat3MulMat3(tmat, tmat, sizemat); - Mat3ToSize(tmat, td->loc); - td->loc[1]= oldy; -} - - -int BoneSize(TransInfo *t, short mval[2]) -{ - TransData *td = t->data; - float size[3], mat[3][3]; - float ratio; - int i; - char str[50]; - - /* for manipulator, center handle, the scaling can't be done relative to center */ - if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) { - ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f; - } - else { - - if(t->flag & T_SHIFT_MOD) { - /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ - float dx= (float)(t->center2d[0] - t->shiftmval[0]); - float dy= (float)(t->center2d[1] - t->shiftmval[1]); - ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; - - dx= (float)(t->center2d[0] - mval[0]); - dy= (float)(t->center2d[1] - mval[1]); - ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio); - - } - else { - float dx= (float)(t->center2d[0] - mval[0]); - float dy= (float)(t->center2d[1] - mval[1]); - ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; - } - - /* flip scale, but not for manipulator center handle */ - if ((t->center2d[0] - mval[0]) * (t->center2d[0] - t->imval[0]) + - (t->center2d[1] - mval[1]) * (t->center2d[1] - t->imval[1]) < 0) - ratio *= -1.0f; - } - - size[0] = size[1] = size[2] = ratio; - - snapGrid(t, size); - - if (hasNumInput(&t->num)) { - applyNumInput(&t->num, size); - constraintNumInput(t, size); - } - - SizeToMat3(size, mat); - - if (t->con.applySize) { - t->con.applySize(t, NULL, mat); - } - - Mat3CpyMat3(t->mat, mat); // used in manipulator - - headerResize(t, size, str); - - for(i = 0 ; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - ElementBoneSize(t, td, mat); - } - - recalcData(t); - - headerprint(str); - - viewRedrawForce(t); - - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); - - return 1; -} - -void initBoneSize(TransInfo *t) -{ - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; - t->transform = BoneSize; - t->fac = (float)sqrt( ( - ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1])) - + - ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0])) - ) ); - - if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf -} - -/* ******************** EditBone envelope *************** */ - -int BoneEnvelope(TransInfo *t, short mval[2]) -{ - TransData *td = t->data; - float ratio; - int i; - char str[50]; - - if(t->flag & T_SHIFT_MOD) { - /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ - float dx= (float)(t->center2d[0] - t->shiftmval[0]); - float dy= (float)(t->center2d[1] - t->shiftmval[1]); - ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; - - dx= (float)(t->center2d[0] - mval[0]); - dy= (float)(t->center2d[1] - mval[1]); - ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio); - - } - else { - float dx= (float)(t->center2d[0] - mval[0]); - float dy= (float)(t->center2d[1] - mval[1]); - ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; - } - - snapGrid(t, &ratio); - - applyNumInput(&t->num, &ratio); - - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[20]; - - outputNumInput(&(t->num), c); - sprintf(str, "Envelope: %s", c); - } - else { - sprintf(str, "Envelope: %3f", ratio); - } - - for(i = 0 ; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if(td->val) *td->val= td->ival*ratio; - } - - recalcData(t); - - headerprint(str); - - force_draw(0); - - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); - - return 1; -} - -void initBoneEnvelope(TransInfo *t) -{ - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; - t->transform = BoneEnvelope; - t->fac = (float)sqrt( ( - ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1])) - + - ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0])) - ) ); - - if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf -} - /* ************************************ */ void BIF_TransformSetUndo(char *str) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 17b8e8461fa..c8f36575eeb 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -836,6 +836,10 @@ static void createTransArmatureVerts(TransInfo *t) if (ebo->flag & BONE_SELECTED) t->total++; } + else if (t->mode==TFM_BONE_ROLL) { + if (ebo->flag & BONE_SELECTED) + t->total++; + } else { if (ebo->flag & BONE_TIPSEL) t->total++; @@ -922,6 +926,21 @@ static void createTransArmatureVerts(TransInfo *t) td++; } } + else if (t->mode==TFM_BONE_ROLL) { + if (ebo->flag & BONE_SELECTED) { + td->loc= NULL; + td->val= &(ebo->roll); + td->ival= ebo->roll; + + VECCOPY (td->center, ebo->head); + td->flag= TD_SELECTED; + + td->ext = NULL; + td->tdi = NULL; + + td++; + } + } else { if (ebo->flag & BONE_TIPSEL){ VECCOPY (td->iloc, ebo->tail); diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 79022b16900..2a9f561a473 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -196,7 +196,7 @@ void snapGrid(TransInfo *t, float *val) { int invert; GearsType action; - if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL) + if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL) invert = U.flag & USER_AUTOROTGRID; else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN) invert = U.flag & USER_AUTOSIZEGRID;