diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 982a2f25df7..82adb1ac12a 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -515,6 +515,7 @@ int handleNDofInput(NDofInput *n, unsigned short event, short val); int manageObjectSpace(int confirm, int set); int manageMeshSpace(int confirm, int set); +int manageBoneSpace(int confirm, int set); /* Those two fill in mat and return non-zero on success */ int createSpaceNormal(float mat[3][3], float normal[3]); diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index 5c06aaea890..050360887b4 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -158,7 +158,7 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags) } /* for pose mode */ -static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *plane) +static void stats_pose(View3D *v3d, bPoseChannel *pchan) { Bone *bone= pchan->bone; @@ -166,9 +166,6 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *p if (bone->flag & BONE_TRANSFORM) { calc_tw_center(pchan->pose_head); protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag); - - VecAddf(normal, normal, pchan->pose_mat[2]); - VecAddf(plane, plane, pchan->pose_mat[1]); } } } @@ -349,26 +346,24 @@ int calc_manipulator_stats(ScrArea *sa) } } else if(ob && (ob->flag & OB_POSEMODE)) { - bArmature *arm= ob->data; + bArmature *arm = ob->data; bPoseChannel *pchan; int mode; if((ob->lay & G.vd->lay)==0) return 0; - mode= Trans.mode; - Trans.mode= TFM_ROTATION; // mislead counting bones... bah + mode = Trans.mode; + Trans.mode = TFM_ROTATION; // mislead counting bones... bah /* count total, we use same method as transform will do */ Trans.total= 0; count_bone_select(&Trans, arm, &arm->bonebase, 1); - totsel= Trans.total; + totsel = Trans.total; if(totsel) { /* use channels to get stats */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - stats_pose(v3d, pchan, normal, plane); + stats_pose(v3d, pchan); } - //VecMulf(normal, -1.0); - VecMulf(plane, -1.0); VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid! Mat4MulVecfl(ob->obmat, G.scene->twcent); @@ -376,7 +371,7 @@ int calc_manipulator_stats(ScrArea *sa) Mat4MulVecfl(ob->obmat, G.scene->twmax); } /* restore, mode can be TFM_INIT */ - Trans.mode= mode; + Trans.mode = mode; } else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) { ; @@ -433,7 +428,7 @@ int calc_manipulator_stats(ScrArea *sa) break; case V3D_MANIP_NORMAL: - if(G.obedit) { + if(G.obedit || ob->flag & OB_POSEMODE) { float mat[3][3]; int type; @@ -479,34 +474,6 @@ int calc_manipulator_stats(ScrArea *sa) } break; } - /* pose mode is a bit weird, so keep it separated */ - else if (ob->flag & OB_POSEMODE) - { - strcpy(t->spacename, "normal"); - if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) { - float imat[3][3], mat[3][3]; - - /* we need the transpose of the inverse for a normal... */ - Mat3CpyMat4(imat, ob->obmat); - - Mat3Inv(mat, imat); - Mat3Transp(mat); - Mat3MulVecfl(mat, normal); - Mat3MulVecfl(mat, plane); - - Normalize(normal); - if(0.0==Normalize(plane)) VECCOPY(plane, mat[1]); - - VECCOPY(mat[2], normal); - Crossf(mat[0], normal, plane); - Crossf(mat[1], mat[2], mat[0]); - - Mat4CpyMat3(v3d->twmat, mat); - Mat4Ortho(v3d->twmat); - - break; - } - } /* no break we define 'normal' as 'local' in Object mode */ case V3D_MANIP_LOCAL: strcpy(t->spacename, "local"); diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 6696fcf95d6..9c7a2f67b89 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -27,6 +27,7 @@ #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" +#include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" #include "DNA_object_types.h" @@ -68,11 +69,17 @@ void BIF_clearTransformOrientation(void) } void BIF_manageTransformOrientation(int confirm, int set) { + Object *ob = OBACT; int index = -1; if (G.obedit) { if (G.obedit->type == OB_MESH) index = manageMeshSpace(confirm, set); + else if (G.obedit->type == OB_ARMATURE) + index = manageBoneSpace(confirm, set); + } + else if (ob && (ob->flag & OB_POSEMODE)) { + index = manageBoneSpace(confirm, set); } else { index = manageObjectSpace(confirm, set); @@ -122,6 +129,31 @@ int confirmSpace(int set, char text[]) } } +int manageBoneSpace(int confirm, int set) { + float mat[3][3]; + float normal[3], plane[3]; + char name[36] = ""; + int index; + + getTransformOrientation(normal, plane, 0); + + if (confirm == 0 && confirmSpace(set, "Bone") == 0) { + return -1; + } + + if (createSpaceNormalTangent(mat, normal, plane) == 0) { + error("Cannot use zero-length bone"); + return -1; + } + + strcpy(name, "Bone"); + + /* Input name */ + sbutton(name, 1, 35, "name: "); + + index = addMatrixSpace(mat, name); + return index; +} int manageMeshSpace(int confirm, int set) { float mat[3][3]; @@ -363,6 +395,29 @@ void applyTransformOrientation() { } } +static int count_bone_select(bArmature *arm, ListBase *lb, int do_it) +{ + Bone *bone; + int do_next; + int total = 0; + + for(bone= lb->first; bone; bone= bone->next) { + bone->flag &= ~BONE_TRANSFORM; + do_next = do_it; + if(do_it) { + if(bone->layer & arm->layer) { + if (bone->flag & BONE_SELECTED) { + bone->flag |= BONE_TRANSFORM; + total++; + do_next= 0; // no transform on children if one parent bone is selected + } + } + } + total += count_bone_select(arm, &bone->childbase, do_next); + } + + return total; +} int getTransformOrientation(float normal[3], float plane[3], int activeOnly) { @@ -375,6 +430,14 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) if(G.obedit) { + float imat[3][3], mat[3][3]; + + /* we need the transpose of the inverse for a normal... */ + Mat3CpyMat4(imat, ob->obmat); + + Mat3Inv(mat, imat); + Mat3Transp(mat); + ob= G.obedit; if(G.obedit->type==OB_MESH) @@ -639,12 +702,48 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) } } - - Mat4Mul3Vecfl(G.obedit->obmat, plane); - Mat4Mul3Vecfl(G.obedit->obmat, normal); + + /* Vectors from edges don't need the special transpose inverse multiplication */ + if (result == ORIENTATION_EDGE) + { + Mat4Mul3Vecfl(ob->obmat, normal); + Mat4Mul3Vecfl(ob->obmat, plane); + } + else + { + Mat3MulVecfl(mat, normal); + Mat3MulVecfl(mat, plane); + } } else if(ob && (ob->flag & OB_POSEMODE)) { + bArmature *arm= ob->data; + bPoseChannel *pchan; + int totsel; + + totsel = count_bone_select(arm, &arm->bonebase, 1); + if(totsel) { + float imat[3][3], mat[3][3]; + + /* use channels to get stats */ + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { + VecAddf(normal, normal, pchan->pose_mat[2]); + VecAddf(plane, plane, pchan->pose_mat[1]); + } + } + VecMulf(plane, -1.0); + + /* we need the transpose of the inverse for a normal... */ + Mat3CpyMat4(imat, ob->obmat); + + Mat3Inv(mat, imat); + Mat3Transp(mat); + Mat3MulVecfl(mat, normal); + Mat3MulVecfl(mat, plane); + + result = ORIENTATION_EDGE; + } } else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) {