- Added operator to clear all transforms from Pose Bones. This makes
authorJoshua Leung <aligorith@gmail.com>
Tue, 11 Jan 2011 11:09:37 +0000 (11:09 +0000)
committerJoshua Leung <aligorith@gmail.com>
Tue, 11 Jan 2011 11:09:37 +0000 (11:09 +0000)
it easier to reset a rig to its default pose again
- Refactored clear pose operators to separate out the common parts,
and made sure that they all had descriptions

release/scripts/ui/space_view3d.py
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/editarmature.c

index 1c5a3351740c2a91887432a8a54606b8f47f0390..eafb46b133d0a87431b643dffea95d0c0ab95971 100644 (file)
@@ -1227,7 +1227,7 @@ class VIEW3D_MT_pose_transform(bpy.types.Menu):
     def draw(self, context):
         layout = self.layout
 
-        layout.label(text="User Transform")
+        layout.operator("pose.transforms_clear", text="All")
 
         layout.operator("pose.loc_clear", text="Location")
         layout.operator("pose.rot_clear", text="Rotation")
index bee0a37d6b185a04a8b089ff5cfedbf77d171373..e8f12bb649cd671b27829d75633587162ebd7a63 100644 (file)
@@ -90,6 +90,7 @@ void POSE_OT_visual_transform_apply(struct wmOperatorType *ot);
 void POSE_OT_rot_clear(struct wmOperatorType *ot);
 void POSE_OT_loc_clear(struct wmOperatorType *ot);
 void POSE_OT_scale_clear(struct wmOperatorType *ot);
+void POSE_OT_transforms_clear(struct wmOperatorType *ot);
 
 void POSE_OT_copy(struct wmOperatorType *ot);
 void POSE_OT_paste(struct wmOperatorType *ot);
index ff4accfd06646e6c1a3b5358cf8f4c06c1df7205..848d3145fa05d129cd06f198ecf29af28ce28f10 100644 (file)
@@ -105,6 +105,7 @@ void ED_operatortypes_armature(void)
        WM_operatortype_append(POSE_OT_rot_clear);
        WM_operatortype_append(POSE_OT_loc_clear);
        WM_operatortype_append(POSE_OT_scale_clear);
+       WM_operatortype_append(POSE_OT_transforms_clear);
        
        WM_operatortype_append(POSE_OT_copy);
        WM_operatortype_append(POSE_OT_paste);
index 935331e3263f5f9c70c0c96f2b8ffc4f44117671..c0ca31b682fb939469fe6708605b7b8ec6d9c5a0 100644 (file)
@@ -4922,21 +4922,158 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob,
 } 
 /* ************* Clear Pose *****************************/
 
-static int pose_clear_scale_exec(bContext *C, wmOperator *UNUSED(op)) 
+/* clear scale of pose-channel */
+static void pchan_clear_scale(bPoseChannel *pchan)
+{
+       if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
+               pchan->size[0]= 1.0f;
+       if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
+               pchan->size[1]= 1.0f;
+       if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
+               pchan->size[2]= 1.0f;
+}
+
+/* clear location of pose-channel */
+static void pchan_clear_loc(bPoseChannel *pchan)
+{
+       if ((pchan->protectflag & OB_LOCK_LOCX)==0)
+               pchan->loc[0]= 0.0f;
+       if ((pchan->protectflag & OB_LOCK_LOCY)==0)
+               pchan->loc[1]= 0.0f;
+       if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
+               pchan->loc[2]= 0.0f;
+}
+
+/* clear rotation of pose-channel */
+static void pchan_clear_rot(bPoseChannel *pchan)
+{
+       if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
+               /* check if convert to eulers for locking... */
+               if (pchan->protectflag & OB_LOCK_ROT4D) {
+                       /* perform clamping on a component by component basis */
+                       if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                               if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                       pchan->rotAngle= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                       pchan->rotAxis[0]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                       pchan->rotAxis[1]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                       pchan->rotAxis[2]= 0.0f;
+                                       
+                               /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+                               if (IS_EQ(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQ(pchan->rotAxis[1], pchan->rotAxis[2]))
+                                       pchan->rotAxis[1] = 1.0f;
+                       }
+                       else if (pchan->rotmode == ROT_MODE_QUAT) {
+                               if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                       pchan->quat[0]= 1.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                       pchan->quat[1]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                       pchan->quat[2]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                       pchan->quat[3]= 0.0f;
+                       }
+                       else {
+                               /* the flag may have been set for the other modes, so just ignore the extra flag... */
+                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                       pchan->eul[0]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                       pchan->eul[1]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                       pchan->eul[2]= 0.0f;
+                       }
+               }
+               else {
+                       /* perform clamping using euler form (3-components) */
+                       float eul[3], oldeul[3], quat1[4] = {0};
+                       float qlen = 0.0f;
+                       
+                       if (pchan->rotmode == ROT_MODE_QUAT) {
+                               qlen= normalize_qt_qt(quat1, pchan->quat);
+                               quat_to_eul(oldeul, quat1);
+                       }
+                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                               axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
+                       }
+                       else {
+                               copy_v3_v3(oldeul, pchan->eul);
+                       }
+                       
+                       eul[0]= eul[1]= eul[2]= 0.0f;
+                       
+                       if (pchan->protectflag & OB_LOCK_ROTX)
+                               eul[0]= oldeul[0];
+                       if (pchan->protectflag & OB_LOCK_ROTY)
+                               eul[1]= oldeul[1];
+                       if (pchan->protectflag & OB_LOCK_ROTZ)
+                               eul[2]= oldeul[2];
+                       
+                       if (pchan->rotmode == ROT_MODE_QUAT) {
+                               eul_to_quat(pchan->quat, eul);
+                               
+                               /* restore original quat size */
+                               mul_qt_fl(pchan->quat, qlen);
+                               
+                               /* quaternions flip w sign to accumulate rotations correctly */
+                               if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+                                       mul_qt_fl(pchan->quat, -1.0f);
+                               }
+                       }
+                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                               eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
+                       }
+                       else {
+                               copy_v3_v3(pchan->eul, eul);
+                       }
+               }
+       }                                               // Duplicated in source/blender/editors/object/object_transform.c
+       else { 
+               if (pchan->rotmode == ROT_MODE_QUAT) {
+                       unit_qt(pchan->quat);
+               }
+               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+                       /* by default, make rotation of 0 radians around y-axis (roll) */
+                       pchan->rotAxis[0]=pchan->rotAxis[2]=pchan->rotAngle= 0.0f;
+                       pchan->rotAxis[1]= 1.0f;
+               }
+               else {
+                       pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
+               }
+       }
+}
+
+/* clear loc/rot/scale of pose-channel */
+static void pchan_clear_transforms(bPoseChannel *pchan)
+{
+       pchan_clear_loc(pchan);
+       pchan_clear_rot(pchan);
+       pchan_clear_scale(pchan);
+}
+
+/* --------------- */
+
+/* generic exec for clear-pose operators */
+static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, 
+               void (*clear_func)(bPoseChannel*), const char default_ksName[])
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
        short autokey = 0;
        
+       /* sanity checks */
+       if ELEM(NULL, clear_func, default_ksName) {
+               BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name");
+               return OPERATOR_CANCELLED;
+       }
+       
        /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
-               if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
-                       pchan->size[0]= 1.0f;
-               if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
-                       pchan->size[1]= 1.0f;
-               if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
-                       pchan->size[2]= 1.0f;
-                       
+       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
+       {
+               /* run provided clearing function */
+               clear_func(pchan);
+               
                /* do auto-keyframing as appropriate */
                if (autokeyframe_cfra_can_key(scene, &ob->id)) {
                        /* clear any unkeyed tags */
@@ -4957,7 +5094,7 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
        /* perform autokeying on the bones if needed */
        if (autokey) {
                /* get KeyingSet to use */
-               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Scaling");
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
                
                /* insert keyframes */
                ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
@@ -4975,11 +5112,19 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
        return OPERATOR_FINISHED;
 }
 
+/* --------------- */
+
+static int pose_clear_scale_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, "Scaling");
+}
+
 void POSE_OT_scale_clear(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Clear Pose Scale";
        ot->idname= "POSE_OT_scale_clear";
+       ot->description = "Reset scaling of selected bones to their default values";
        
        /* api callbacks */
        ot->exec = pose_clear_scale_exec;
@@ -4989,58 +5134,31 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int pose_clear_loc_exec(bContext *C, wmOperator *UNUSED(op)) 
+
+static int pose_clear_rot_exec(bContext *C, wmOperator *op) 
 {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
-       short autokey = 0;
-       
-       /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
-               /* clear location */
-               if ((pchan->protectflag & OB_LOCK_LOCX)==0)
-                       pchan->loc[0]= 0.0f;
-               if ((pchan->protectflag & OB_LOCK_LOCY)==0)
-                       pchan->loc[1]= 0.0f;
-               if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
-                       pchan->loc[2]= 0.0f;
-                       
-               /* do auto-keyframing as appropriate */
-               if (autokeyframe_cfra_can_key(scene, &ob->id)) {
-                       /* clear any unkeyed tags */
-                       if (pchan->bone)
-                               pchan->bone->flag &= ~BONE_UNKEYED;
-                               
-                       /* tag for autokeying later */
-                       autokey = 1;
-               }
-               else {
-                       /* add unkeyed tags */
-                       if (pchan->bone)
-                               pchan->bone->flag |= BONE_UNKEYED;
-               }
-       }
-       CTX_DATA_END;
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, "Rotation");
+}
+
+void POSE_OT_rot_clear(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Clear Pose Rotation";
+       ot->idname= "POSE_OT_rot_clear";
+       ot->description = "Reset rotations of selected bones to their default values";
        
-       /* perform autokeying on the bones if needed */
-       if (autokey) {
-               /* get KeyingSet to use */
-               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Location");
-               
-               /* insert keyframes */
-               ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-               
-               /* now recalculate paths */
-               if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
-                       ED_pose_recalculate_paths(scene, ob);
-       }
+       /* api callbacks */
+       ot->exec = pose_clear_rot_exec;
+       ot->poll = ED_operator_posemode;
        
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
-       
-       return OPERATOR_FINISHED;
+
+static int pose_clear_loc_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, "Location");
 }
 
 void POSE_OT_loc_clear(wmOperatorType *ot)
@@ -5048,6 +5166,7 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Clear Pose Location";
        ot->idname= "POSE_OT_loc_clear";
+       ot->description = "Reset locations of selected bones to their default values";
        
        /* api callbacks */
        ot->exec = pose_clear_loc_exec;
@@ -5057,161 +5176,25 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int pose_clear_rot_exec(bContext *C, wmOperator *UNUSED(op)) 
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
-       short autokey = 0;
-       
-       /* only clear those channels that are not locked */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
-               if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
-                       /* check if convert to eulers for locking... */
-                       if (pchan->protectflag & OB_LOCK_ROT4D) {
-                               /* perform clamping on a component by component basis */
-                               if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
-                                               pchan->rotAngle= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
-                                               pchan->rotAxis[0]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
-                                               pchan->rotAxis[1]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
-                                               pchan->rotAxis[2]= 0.0f;
-                                               
-                                       /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
-                                       if (IS_EQ(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQ(pchan->rotAxis[1], pchan->rotAxis[2]))
-                                               pchan->rotAxis[1] = 1.0f;
-                               }
-                               else if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
-                                               pchan->quat[0]= 1.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
-                                               pchan->quat[1]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
-                                               pchan->quat[2]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
-                                               pchan->quat[3]= 0.0f;
-                               }
-                               else {
-                                       /* the flag may have been set for the other modes, so just ignore the extra flag... */
-                                       if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
-                                               pchan->eul[0]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
-                                               pchan->eul[1]= 0.0f;
-                                       if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
-                                               pchan->eul[2]= 0.0f;
-                               }
-                       }
-                       else {
-                               /* perform clamping using euler form (3-components) */
-                               float eul[3], oldeul[3], quat1[4] = {0};
-                               float qlen = 0.0f;
-                               
-                               if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       qlen= normalize_qt_qt(quat1, pchan->quat);
-                                       quat_to_eul(oldeul, quat1);
-                               }
-                               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       axis_angle_to_eulO( oldeul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
-                               }
-                               else {
-                                       copy_v3_v3(oldeul, pchan->eul);
-                               }
-                               
-                               eul[0]= eul[1]= eul[2]= 0.0f;
-                               
-                               if (pchan->protectflag & OB_LOCK_ROTX)
-                                       eul[0]= oldeul[0];
-                               if (pchan->protectflag & OB_LOCK_ROTY)
-                                       eul[1]= oldeul[1];
-                               if (pchan->protectflag & OB_LOCK_ROTZ)
-                                       eul[2]= oldeul[2];
-                               
-                               if (pchan->rotmode == ROT_MODE_QUAT) {
-                                       eul_to_quat(pchan->quat, eul);
-                                       
-                                       /* restore original quat size */
-                                       mul_qt_fl(pchan->quat, qlen);
-                                       
-                                       /* quaternions flip w sign to accumulate rotations correctly */
-                                       if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
-                                               mul_qt_fl(pchan->quat, -1.0f);
-                                       }
-                               }
-                               else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                                       eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
-                               }
-                               else {
-                                       copy_v3_v3(pchan->eul, eul);
-                               }
-                       }
-               }                                               // Duplicated in source/blender/editors/object/object_transform.c
-               else { 
-                       if (pchan->rotmode == ROT_MODE_QUAT) {
-                               unit_qt(pchan->quat);
-                       }
-                       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
-                               /* by default, make rotation of 0 radians around y-axis (roll) */
-                               pchan->rotAxis[0]=pchan->rotAxis[2]=pchan->rotAngle= 0.0f;
-                               pchan->rotAxis[1]= 1.0f;
-                       }
-                       else {
-                               pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f;
-                       }
-               }
-               
-               /* do auto-keyframing as appropriate */
-               if (autokeyframe_cfra_can_key(scene, &ob->id)) {
-                       /* clear any unkeyed tags */
-                       if (pchan->bone)
-                               pchan->bone->flag &= ~BONE_UNKEYED;
-                               
-                       /* tag for autokeying later */
-                       autokey = 1;
-               }
-               else {
-                       /* add unkeyed tags */
-                       if (pchan->bone)
-                               pchan->bone->flag |= BONE_UNKEYED;
-               }
-       }
-       CTX_DATA_END;
-       
-       /* perform autokeying on the bones if needed */
-       if (autokey) {
-               /* get KeyingSet to use */
-               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "Rotation");
-               
-               /* insert keyframes */
-               ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-               
-               /* now recalculate paths */
-               if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
-                       ED_pose_recalculate_paths(scene, ob);
-       }
-       
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
-       /* note, notifier might evolve */
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
-       
-       return OPERATOR_FINISHED;
+static int pose_clear_transforms_exec(bContext *C, wmOperator *op) 
+{
+       return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, "LocRotScale");
 }
 
-void POSE_OT_rot_clear(wmOperatorType *ot)
+void POSE_OT_transforms_clear(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Clear Pose Rotation";
-       ot->idname= "POSE_OT_rot_clear";
+       ot->name= "Clear Pose Transforms";
+       ot->idname= "POSE_OT_transforms_clear";
+       ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
        
        /* api callbacks */
-       ot->exec = pose_clear_rot_exec;
+       ot->exec = pose_clear_transforms_exec;
        ot->poll = ED_operator_posemode;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
 }
 
 /* ***************** selections ********************** */