diff options
author | Joshua Leung <aligorith@gmail.com> | 2011-01-11 14:09:37 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2011-01-11 14:09:37 +0300 |
commit | 7225efeba04541c30430cced9c24da3b73a2e8da (patch) | |
tree | 290fdd6d457884a16bbebae04c639d6e9dabc9bc /source/blender/editors/armature/editarmature.c | |
parent | 8d385404ab0aefd38190f1e6844240c4eb5b267d (diff) |
- Added operator to clear all transforms from Pose Bones. This makes
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
Diffstat (limited to 'source/blender/editors/armature/editarmature.c')
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 387 |
1 files changed, 185 insertions, 202 deletions
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 935331e3263..c0ca31b682f 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -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 ********************** */ |