diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2012-05-13 20:01:59 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2012-05-13 20:01:59 +0400 |
commit | 800bc74a8f57ee5c993924fae28fb2223542fc67 (patch) | |
tree | 14e182d0b6e7db9933a96f176d250b9e78d302c3 | |
parent | c8ebfe1d12f87ae453fc9191fa7e3ae30aa800d4 (diff) |
Adds “align” option to snap to verts/edges/faces, for bones in Pose mode.
Have to use a ugly hack, as for pose bones, rotscale transform matrix is not always the same as translate one... :/
Adresses feature request [#30979] snapping: "align rotation with the snapping target" and pose-mode.
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 26 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 15 |
4 files changed, 36 insertions, 11 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 6efbb99701a..b3ac9481931 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -93,7 +93,7 @@ class VIEW3D_HT_header(Header): if snap_element != 'INCREMENT': row.prop(toolsettings, "snap_target", text="") if obj: - if obj.mode == 'OBJECT' and snap_element != 'VOLUME': + if obj.mode in {'OBJECT','POSE'} and snap_element != 'VOLUME': row.prop(toolsettings, "use_snap_align_rotation", text="") elif obj.mode == 'EDIT': row.prop(toolsettings, "use_snap_self", text="") diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8b472fd987f..5c605e02fd1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3035,12 +3035,16 @@ 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 + /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same, + * and ElementRotation() might be called in Translation context (with align snapping), + * we need to be sure to actually use the *rotation* matrix here... + * So no other way than storing it in some dedicated members of td->ext! */ + if ((t->flag & T_V3D_ALIGN)==0) { /* align mode doesn't rotate objects itself */ /* euler or quaternion/axis-angle? */ if (td->ext->rotOrder == ROT_MODE_QUAT) { - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); + mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL); - mat3_to_quat(quat, fmat); // Actual transform + mat3_to_quat(quat, fmat); /* Actual transform */ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); /* this function works on end result */ @@ -3053,8 +3057,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); - mat3_to_quat(quat, fmat); // Actual transform + mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL); + mat3_to_quat(quat, fmat); /* Actual transform */ mul_qt_qtqt(tquat, quat, iquat); quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); @@ -3065,8 +3069,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short else { float eulmat[3][3]; - mul_m3_m3m3(totmat, mat, td->mtx); - mul_m3_m3m3(smat, td->smtx, totmat); + mul_m3_m3m3(totmat, mat, td->ext->r_mtx); + mul_m3_m3m3(smat, td->ext->r_smtx, totmat); /* calculate the total rotatation in eulers */ copy_v3_v3(eul, td->ext->irot); @@ -3472,12 +3476,18 @@ static void applyTranslation(TransInfo *t, float vec[3]) /* handle snapping rotation before doing the translation */ if (usingSnappingNormal(t)) { if (validSnappingNormal(t)) { - float *original_normal = td->axismtx[2]; + float *original_normal; float axis[3]; float quat[4]; float mat[3][3]; float angle; + /* In pose mode, we want to align normals with Y axis of bones... */ + if (t->flag & T_POSE) + original_normal = td->axismtx[1]; + else + original_normal = td->axismtx[2]; + cross_v3_v3v3(axis, original_normal, t->tsnap.snapNormal); angle = saacos(dot_v3v3(original_normal, t->tsnap.snapNormal)); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index c7cb7b179ae..f902659a5c5 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -137,6 +137,10 @@ typedef struct TransDataExtension { float isize[3]; /* Initial size */ float obmat[4][4]; /* Object matrix */ float l_smtx[3][3]; /* use instead of td->smtx, It is the same but without the 'bone->bone_mat', see TD_PBONE_LOCAL_MTX_C */ + float r_mtx[3][3]; /* The rotscale matrix of pose bone, to allow using snap-align in translation mode, + * when td->mtx is the loc pose bone matrix (and hence can't be used to apply rotation in some cases, + * namely when a bone is in "NoLocal" or "Hinge" mode)... */ + float r_smtx[3][3]; /* Invers of previous one. */ int rotOrder; /* rotation mode, as defined in eRotationModes (DNA_action_types.h) */ } TransDataExtension; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index b457d22a712..c4db85420ca 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -538,6 +538,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr /* New code, using "generic" BKE_pchan_to_pose_mat(). */ { float rotscale_mat[4][4], loc_mat[4][4]; + float rpmat[3][3]; BKE_pchan_to_pose_mat(pchan, rotscale_mat, loc_mat); if (t->mode == TFM_TRANSLATION) @@ -545,13 +546,23 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr else copy_m3_m4(pmat, rotscale_mat); + /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal, + * and want align snapping, we just need both loc_mat and rotscale_mat. + * So simply always store rotscale mat in td->ext, and always use it to apply rotations... + * Ugly to need such hacks! :/ */ + copy_m3_m4(rpmat, rotscale_mat); + if (constraints_list_needinv(t, &pchan->constraints)) { copy_m3_m4(tmat, pchan->constinv); invert_m3_m3(cmat, tmat); mul_serie_m3(td->mtx, pmat, omat, cmat, NULL, NULL, NULL, NULL, NULL); + mul_serie_m3(td->ext->r_mtx, rpmat, omat, cmat, NULL,NULL,NULL,NULL,NULL); } - else - mul_serie_m3(td->mtx, pmat, omat, NULL, NULL, NULL, NULL, NULL, NULL); + else { + mul_serie_m3(td->mtx, pmat, omat, NULL, NULL,NULL,NULL,NULL,NULL); + mul_serie_m3(td->ext->r_mtx, rpmat, omat, NULL, NULL,NULL,NULL,NULL,NULL); + } + invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx); } invert_m3_m3(td->smtx, td->mtx); |