diff options
author | Sybren A. Stüvel <sybren@stuvel.eu> | 2018-03-09 21:03:29 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@stuvel.eu> | 2018-03-09 21:03:29 +0300 |
commit | 14e7ba0c8ac7f229a1b025103a786f267dfb9387 (patch) | |
tree | ec21769ee9f799f330ec8837c00ffd71ad4736f8 /source/blender/editors/armature | |
parent | 40e62f271c137f6bce19c6f6497948d014a7ab17 (diff) |
Fix Pose Lib: pose is applied when selected bones don't overlap with pose
Premise: When pose bones are selected, applying a pose library should
only affect the selected bones.
This commit fixes a bug where the pose was also applied when there was
no overlap between the selected bones and the bones in the pose. For
example, applying a pose which contains only keyframes for the left
hand, while only right-hand bones are selected, would apply the pose
to the left hand anyway.
The code is now also slightly more efficient; the removed 'selcount'
counter was only used as a binary (i.e. zero or non-zero). It's now
stored as a bitflag instead.
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r-- | source/blender/editors/armature/pose_lib.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 587ae6991a2..d9d5fa395d6 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -833,7 +833,6 @@ typedef struct tPoseLib_PreviewData { bAction *act; /* poselib to use */ TimeMarker *marker; /* 'active' pose */ - int selcount; /* number of selected elements to work on */ int totcount; /* total number of elements to work on */ short state; /* state of main loop */ @@ -866,7 +865,8 @@ enum { /* defines for tPoseLib_PreviewData->flag values */ enum { PL_PREVIEW_FIRSTTIME = (1 << 0), - PL_PREVIEW_SHOWORIGINAL = (1 << 1) + PL_PREVIEW_SHOWORIGINAL = (1 << 1), + PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2), }; /* ---------------------------- */ @@ -886,7 +886,20 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld) { bActionGroup *agrp; bPoseChannel *pchan; - + bool selected = false; + + /* determine whether any bone is selected. */ + LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) { + selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED; + if (selected) { + pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED; + break; + } + } + if (!selected) { + pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED; + } + /* for each posechannel that has an actionchannel in */ for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) { /* try to find posechannel */ @@ -908,8 +921,6 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld) BLI_addtail(&pld->backups, plb); /* mark as being affected */ - if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) - pld->selcount++; pld->totcount++; } } @@ -970,6 +981,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) KeyframeEditData ked = {{NULL}}; KeyframeEditFunc group_ok_cb; int frame = 1; + const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED; /* get the frame */ if (pld->marker) @@ -982,8 +994,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); ked.f1 = ((float)frame) - 0.5f; ked.f2 = ((float)frame) + 0.5f; - - + /* start applying - only those channels which have a key at this point in time! */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* check if group has any keyframes */ @@ -995,7 +1006,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) bool ok = 0; /* check if this bone should get any animation applied */ - if (pld->selcount == 0) { + if (!any_bone_selected) { /* if no bones are selected, then any bone is ok */ ok = 1; } @@ -1008,7 +1019,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) ok = 1; } } - + if (ok) animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame); } @@ -1027,14 +1038,15 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID); ListBase dsources = {NULL, NULL}; bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id); - + const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED; + /* start tagging/keying */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* only for selected bones unless there aren't any selected, in which case all are included */ pchan = BKE_pose_channel_find_name(pose, agrp->name); if (pchan) { - if ((pld->selcount == 0) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { + if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { if (autokey) { /* add datasource override for the PoseChannel, to be used later */ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); |