== Apply Current Pose as New Restpose ==
authorJoshua Leung <aligorith@gmail.com>
Thu, 28 Aug 2008 12:22:55 +0000 (12:22 +0000)
committerJoshua Leung <aligorith@gmail.com>
Thu, 28 Aug 2008 12:22:55 +0000 (12:22 +0000)
In PoseMode, the Ctrl-A hotkey can now be used to apply the current pose as the new restpose for the armature.

Notes:
* Roll correction may not be totally correct on bone chains, but is ok in most cases.
* Objects that are bone parented to the armature where this is applied are not correctly adjusted yet.
* It is advisable to 'apply' the existing armature deformations to geometry deformed by the armature before applying this, to prevent unexpected results.
* No menu entry yet... will add in due course.

source/blender/include/BIF_editarmature.h
source/blender/src/editarmature.c
source/blender/src/editobject.c
source/blender/src/space.c

index 07fc8f08b4a0a7be2e51fb366e15be1f4f10dc85..b2bdb2dad73c81daac16622e605e0e5e19833453 100644 (file)
@@ -91,6 +91,7 @@ void  free_editArmature(void);
 
 int            join_armature(void);
 void   separate_armature(void);
+void   apply_armature_pose2bones(void);
 void   load_editArmature(void);
 
 void   make_bone_parent(void);
index 35986fcff4aa392ea3699a4dbad5946abd0c73b4..01a0c330b47a31069d8f7b81201a0561e24421ac 100644 (file)
@@ -439,6 +439,90 @@ void docenter_armature (Object *ob, int centermode)
        }
 }
 
+/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
+static void applyarmature_fix_boneparents (Object *ob)
+{
+       
+}
+
+/* set the current pose as the restpose */
+void apply_armature_pose2bones(void)
+{
+       Object  *ob;
+       bArmature *arm;
+       bPose *pose;
+       bPoseChannel *pchan;
+       EditBone *curbone;
+       
+       /* don't check if editmode (should be done by caller) */
+       ob= OBACT;
+       if (ob->type!=OB_ARMATURE) return;
+       if (object_data_is_libdata(ob)) {
+               error_libdata();
+               return;
+       }
+       arm= get_armature(ob); 
+       
+       /* Get editbones of active armature to alter */
+       if (G.edbo.first) BLI_freelistN(&G.edbo);
+       make_boneList(&G.edbo, &arm->bonebase, NULL);
+       
+       /* get pose of active object and move it out of posemode */
+       pose= ob->pose;
+       
+       for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
+               curbone= editbone_name_exists(&G.edbo, pchan->name);
+               
+               /* simply copy the head/tail values from pchan over to curbone */
+               VECCOPY(curbone->head, pchan->pose_head);
+               VECCOPY(curbone->tail, pchan->pose_tail);
+               
+               /* fix roll:
+                *      1. find auto-calculated roll value for this bone now
+                *      2. remove this from the 'visual' y-rotation
+                */
+               {
+                       float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3];
+                       float delta[3], eul[3];
+                       
+                       /* obtain new auto-yrotation */
+                       VecSubf(delta, curbone->tail, curbone->head);
+                       vec_roll_to_mat3(delta, curbone->roll, premat);
+                       Mat3Inv(imat, premat);
+                       
+                       /* get pchan 'visual' matrix */
+                       Mat3CpyMat4(pmat, pchan->pose_mat);
+                       
+                       /* remove auto from visual and get euler rotation */
+                       Mat3MulMat3(tmat, imat, pmat);
+                       Mat3ToEul(tmat, eul);
+                       
+                       /* just use this euler-y as new roll value */
+                       curbone->roll= eul[1];
+               }
+               
+               /* clear transform values for pchan */
+               pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0;
+               pchan->size[0]= pchan->size[1]= pchan->size[2]= 1;
+               pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0;
+               pchan->quat[0]= 1;
+       }
+       
+       /* convert editbones back to bones */
+       editbones_to_armature(&G.edbo, ob);
+       if (G.edbo.first) BLI_freelistN(&G.edbo);
+       
+       /* flush positions of posebones */
+       where_is_pose(ob);
+       
+       /* fix parenting of objects which are bone-parented */
+       applyarmature_fix_boneparents(ob);
+       
+       BIF_undo_push("Apply new restpose");
+       allqueue(REDRAWVIEW3D, 0);
+}
+
+
 /* Helper function for armature joining - link fixing */
 static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
 {
index 1ba7bce6dabfc77114a0c0d82cd9e4869fdc6c5f..dded38a00e87b6e8cbddc6d5a1cf7e4b0a1802b6 100644 (file)
@@ -4130,15 +4130,26 @@ void apply_object( void )
                }
                allqueue(REDRAWVIEW3D, 0);
                
-       } else {
+       } 
+       else {
+               ob= OBACT;
                
-               evt = pupmenu("Apply Object%t|Scale and Rotation to ObData|Visual Transform to Objects Loc/Scale/Rot");
+               if ((ob->pose) && (ob->flag & OB_POSEMODE))
+                       evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3");
+               else
+                       evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2");
                if (evt==-1) return;
                
-               if (evt==1) {
-                       apply_objects_locrot();
-               } else if (evt==2) {
-                       apply_objects_visual_tx();
+               switch (evt) {
+                       case 1:
+                               apply_objects_locrot();
+                               break;
+                       case 2:
+                               apply_objects_visual_tx();
+                               break;
+                       case 3:
+                               apply_armature_pose2bones();
+                               break;
                }
        }
 }
index 8ca26ea57ab245c33a06f392e6fe29fe96da56c9..b19d20e1be52097e394a938cb2bb05f13f44e97c 100644 (file)
@@ -1966,7 +1966,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                G.vd->drawtype= pupval;
                                                doredraw= 1;
                                        }
-                                }
+                }
                                
                                break;
                        case EKEY: