diff options
author | Joshua Leung <aligorith@gmail.com> | 2012-08-18 09:14:21 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2012-08-18 09:14:21 +0400 |
commit | cc1a89faee7a88b1320cb28c0350c76302fe0f05 (patch) | |
tree | b7b7b6430e00c12c2a87ca70f3768963b30d93bb /source/blender/editors/animation/anim_deps.c | |
parent | 246c86c9262668d13b13f76957e1b2ed74733d4f (diff) |
Bugfix [#27652] Selecting a bone doesn't update Driver Properties panel
More specifically, selecting bones didn't update the active F-Curve/Groups. This
meant that when editing drivers, it was often easy to accidentally edit the
drivers for the wrong bone.
Diffstat (limited to 'source/blender/editors/animation/anim_deps.c')
-rw-r--r-- | source/blender/editors/animation/anim_deps.c | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 3cc39238713..3e0380929f8 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -125,7 +125,7 @@ void ANIM_id_update(Scene *UNUSED(scene), ID *id) */ /* perform syncing updates for Action Groups */ -static void animchan_sync_group(bAnimContext *UNUSED(ac), bAnimListElem *ale) +static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp) { bActionGroup *agrp = (bActionGroup *)ale->data; ID *owner_id = ale->id; @@ -143,22 +143,42 @@ static void animchan_sync_group(bAnimContext *UNUSED(ac), bAnimListElem *ale) /* check if there are bones, and whether the name matches any * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone */ + // TODO: if bone gets renamed, it would be best to be able to rename the group + // TODO: sync bone/group colors if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); + bArmature *arm = ob->data; - /* if one matches, sync the selection status */ if (pchan) { - if (pchan->bone && pchan->bone->flag & BONE_SELECTED) + /* if one matches, sync the selection status */ + if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) agrp->flag |= AGRP_SELECTED; else agrp->flag &= ~AGRP_SELECTED; + + /* also sync active group status */ + if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) { + /* if no previous F-Curve has active flag, then we're the first and only one to get it */ + if (*active_agrp == NULL) { + agrp->flag |= AGRP_ACTIVE; + *active_agrp = agrp; + } + else { + /* someone else has already taken it - set as not active */ + agrp->flag &= ~AGRP_ACTIVE; + } + } + else { + /* this can't possibly be active now */ + agrp->flag &= ~AGRP_ACTIVE; + } } } } } /* perform syncing updates for F-Curves */ -static void animchan_sync_fcurve(bAnimContext *UNUSED(ac), bAnimListElem *ale) +static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **active_fcurve) { FCurve *fcu = (FCurve *)ale->data; ID *owner_id = ale->id; @@ -168,12 +188,13 @@ static void animchan_sync_fcurve(bAnimContext *UNUSED(ac), bAnimListElem *ale) */ if (ELEM3(NULL, fcu, fcu->rna_path, owner_id)) return; - + if (GS(owner_id->name) == ID_OB) { Object *ob = (Object *)owner_id; /* only affect if F-Curve involves pose.bones */ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { + bArmature *arm = (bArmature *)ob->data; bPoseChannel *pchan; char *bone_name; @@ -184,10 +205,30 @@ static void animchan_sync_fcurve(bAnimContext *UNUSED(ac), bAnimListElem *ale) /* F-Curve selection depends on whether the bone is selected */ if ((pchan) && (pchan->bone)) { + /* F-Curve selection */ if (pchan->bone->flag & BONE_SELECTED) fcu->flag |= FCURVE_SELECTED; else fcu->flag &= ~FCURVE_SELECTED; + + /* Active F-Curve - it should be the first one for this bone on the + * active object to be considered as active + */ + if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) { + /* if no previous F-Curve has active flag, then we're the first and only one to get it */ + if (*active_fcurve == NULL) { + fcu->flag |= FCURVE_ACTIVE; + *active_fcurve = fcu; + } + else { + /* someone else has already taken it - set as not active */ + fcu->flag &= ~FCURVE_ACTIVE; + } + } + else { + /* this can't possibly be active now */ + fcu->flag &= ~FCURVE_ACTIVE; + } } } } @@ -248,25 +289,30 @@ void ANIM_sync_animchannels_to_data(const bContext *C) bAnimListElem *ale; int filter; + bActionGroup *active_agrp = NULL; + FCurve *active_fcurve = NULL; + /* get animation context info for filtering the channels */ // TODO: check on whether we need to set the area specially instead, since active area might not be ok? if (ANIM_animdata_get_context(C, &ac) == 0) return; /* filter data */ - /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */ - filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS; + /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed + * However, don't include duplicates so that selection statuses don't override each other + */ + filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS; ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* flush settings as appropriate depending on the types of the channels */ for (ale = anim_data.first; ale; ale = ale->next) { switch (ale->type) { case ANIMTYPE_GROUP: - animchan_sync_group(&ac, ale); + animchan_sync_group(&ac, ale, &active_agrp); break; case ANIMTYPE_FCURVE: - animchan_sync_fcurve(&ac, ale); + animchan_sync_fcurve(&ac, ale, &active_fcurve); break; } } |