diff options
author | Joshua Leung <aligorith@gmail.com> | 2006-12-22 12:05:37 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2006-12-22 12:05:37 +0300 |
commit | fcd3ea7875d3a8bde7dc642b7c45d5ba806c94e2 (patch) | |
tree | e8bd81c202f5e98a0fdf77ac517776856d5ed207 /source/blender/src/edit.c | |
parent | e7d916b6e67dafc205c37f0df4eec82381e5e557 (diff) |
== Snap Bones To Location in PoseMode ==
Now the Snap To Location (Shift S) tools for bones in pose-mode
work correctly. Previously, only one of these tools was implemented,
but it only worked in some cases.
This fixes item #4874 in Todo Tracker. Was patch #5012.
Diffstat (limited to 'source/blender/src/edit.c')
-rw-r--r-- | source/blender/src/edit.c | 128 |
1 files changed, 119 insertions, 9 deletions
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index b915e1b6627..5e174e8fa47 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -1103,7 +1103,52 @@ void snap_sel_to_grid() if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) { ob= base->object; if(ob->flag & OB_POSEMODE) { - ; // todo + bPoseChannel *pchan; + bArmature *arm= ob->data; + + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if(pchan->bone->flag & BONE_SELECTED) { + if(pchan->bone->layer & arm->layer) { + if (pchan->parent==NULL) { + float dLoc[3], oldLoc[3], nLoc[3]; + + /* get nearest grid point to snap to */ + VECCOPY(nLoc, pchan->pose_head); + vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf)); + vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf)); + vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf)); + + /* adjust location */ + VecSubf(dLoc, vec, nLoc); + VECCOPY(oldLoc, pchan->loc); + VecAddf(pchan->loc, oldLoc, dLoc); + } + else if((pchan->bone->flag & BONE_CONNECTED)==0) { + float vecN[3], nLoc[3]; + float dLoc[3], oldLoc[3]; + + /* get nearest grid point to snap to */ + VECCOPY(nLoc, pchan->pose_mat[3]); + vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf)); + vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf)); + vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf)); + + /* get bone-space location of grid point */ + armature_loc_pose_to_bone(pchan, vec, vecN); + + /* adjust location */ + VECCOPY(oldLoc, pchan->loc); + VecSubf(dLoc, vecN, oldLoc); + VecAddf(pchan->loc, oldLoc, dLoc); + } + /* if the bone has a parent and is connected to the parent, + * don't do anything - will break chain unless we do auto-ik. + */ + } + } + } + ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); + ob->recalc |= OB_RECALC_DATA; } else { ob->recalc |= OB_RECALC_OB; @@ -1196,10 +1241,26 @@ void snap_sel_to_curs() if(pchan->bone->flag & BONE_SELECTED) { if(pchan->bone->layer & arm->layer) { if(pchan->parent==NULL) { - /* this is wrong... lazy! */ - VECCOPY(pchan->loc, cursp); + float dLoc[3], oldLoc[3]; + + VecSubf(dLoc, cursp, pchan->pose_head); + VECCOPY(oldLoc, pchan->loc); + VecAddf(pchan->loc, oldLoc, dLoc); + } + else if((pchan->bone->flag & BONE_CONNECTED)==0) { + float curspn[3], dLoc[3], oldLoc[3]; + + /* get location of cursor in bone-space */ + armature_loc_pose_to_bone(pchan, cursp, curspn); + + /* calculate new position */ + VECCOPY(oldLoc, pchan->loc); + VecSubf(dLoc, curspn, oldLoc); + VecAddf(pchan->loc, oldLoc, dLoc); } - /* else todo... */ + /* if the bone has a parent and is connected to the parent, + * don't do anything - will break chain unless we do auto-ik. + */ } } } @@ -1459,10 +1520,29 @@ void snap_to_center() base= (G.scene->base.first); while(base) { if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) { - VECCOPY(vec, base->object->obmat[3]); - VecAddf(centroid, centroid, vec); - DO_MINMAX(vec, min, max); - count++; + ob= base->object; + if(ob->flag & OB_POSEMODE) { + bPoseChannel *pchan; + bArmature *arm= ob->data; + + for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if(pchan->bone->flag & BONE_SELECTED) { + if(pchan->bone->layer & arm->layer) { + VECCOPY(vec, pchan->pose_mat[3]); + VecAddf(centroid, centroid, vec); + DO_MINMAX(vec, min, max); + count++; + } + } + } + } + else { + /* not armature bones (i.e. objects) */ + VECCOPY(vec, base->object->obmat[3]); + VecAddf(centroid, centroid, vec); + DO_MINMAX(vec, min, max); + count++; + } } base= base->next; } @@ -1514,7 +1594,37 @@ void snap_to_center() if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) { ob= base->object; if(ob->flag & OB_POSEMODE) { - ; // todo + bPoseChannel *pchan; + bArmature *arm= ob->data; + + for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if(pchan->bone->flag & BONE_SELECTED) { + if(pchan->bone->layer & arm->layer) { + if(pchan->parent==NULL) { + float dLoc[3], oldLoc[3]; + VecSubf(dLoc, snaploc, pchan->pose_head); + VECCOPY(oldLoc, pchan->loc); + VecAddf(pchan->loc, oldLoc, dLoc); + } + else if((pchan->bone->flag & BONE_CONNECTED)==0) { + float dLoc[3], oldLoc[3]; + + /* get location of cursor in bone-space */ + armature_loc_pose_to_bone(pchan, snaploc, vec); + + /* calculate new position */ + VECCOPY(oldLoc, pchan->loc); + VecSubf(dLoc, vec, oldLoc); + VecAddf(pchan->loc, oldLoc, dLoc); + } + /* if the bone has a parent and is connected to the parent, + * don't do anything - will break chain unless we do auto-ik. + */ + } + } + } + ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); + ob->recalc |= OB_RECALC_DATA; } else { ob->recalc |= OB_RECALC_OB; |