Fix #95855: prioritize selecting keys on active fcurve

This addresses #95855 by prioritizing the selection of keys in the following order:

1. Keys on the active curve.
2. Keys on any selected curve.
3. Other keys.

Additionally, this fixes an as-yet unreported issue where you couldn't select the main vertex of a key if it was overlapping with another one and one or more of its handle vertices were already selected.  This was due to the selection status of a key and its handles not being properly considered separately.

Pull Request: blender/blender#107223
This commit is contained in:
2023-05-04 10:10:34 +02:00
committed by Nathan Vegdahl
parent f428fd8229
commit 10a93aebf1

View File

@@ -143,7 +143,8 @@ static void nearest_fcurve_vert_store(ListBase *matches,
nvi->frame = bezt->vec[1][0]; /* currently in global time... */
nvi->sel = BEZT_ISSEL_ANY(bezt); /* XXX... should this use the individual verts instead? */
/* NOTE: `hpoint` is -1,0,1, but `BEZT_ISSEL_IDX` expects 0,1,2. */
nvi->sel = BEZT_ISSEL_IDX(bezt, hpoint + 1);
/* add to list of matches if appropriate... */
if (replace == 0) {
@@ -259,9 +260,6 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
/* helper for find_nearest_fcurve_vert() - get the best match to use */
static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
{
tNearestVertInfo *nvi = NULL;
short found = 0;
/* abort if list is empty */
if (BLI_listbase_is_empty(matches)) {
return NULL;
@@ -273,27 +271,49 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
return BLI_pophead(matches);
}
/* try to find the first selected F-Curve vert, then take the one after it */
for (nvi = matches->first; nvi; nvi = nvi->next) {
/* which mode of search are we in: find first selected, or find vert? */
if (found) {
/* Just take this vert now that we've found the selected one
* - We'll need to remove this from the list
* so that it can be returned to the original caller.
*/
BLI_remlink(matches, nvi);
return nvi;
}
/* The goal of the remaining code below is to prioritize selecting verts on
* selected fcurves, but to still cycle through the vertices in `matches` if
* a selected-fcurve vertex is already selected. */
/* if vert is selected, we've got what we want... */
/* Try to find the first selected vert in `matches`. Additionally, if
* one exists, rotate `matches` to put it last in the list and the vert
* following it first, since that's the order we'll want to scan in. */
tNearestVertInfo *nvi_first_selected = NULL;
LISTBASE_FOREACH (tNearestVertInfo *, nvi, matches) {
if (nvi->sel) {
found = 1;
nvi_first_selected = nvi;
BLI_listbase_rotate_last(matches, nvi_first_selected);
break;
}
}
/* if we're still here, this means that we failed to find anything appropriate in the first pass,
* so just take the first item now...
*/
/* Try to find the next vert that's on the active fcurve, falling back
* to the next vert on any selected fcurve if that's not found. */
tNearestVertInfo *nvi_to_select = NULL;
LISTBASE_FOREACH (tNearestVertInfo *, nvi, matches) {
if (nvi == nvi_first_selected) {
continue;
}
if (nvi->fcu->flag & FCURVE_ACTIVE) {
nvi_to_select = nvi;
break;
}
if (nvi->fcu->flag & FCURVE_SELECTED && !nvi_to_select) {
nvi_to_select = nvi;
}
}
/* If we found a vert on a selected fcurve, return it. */
if (nvi_to_select) {
BLI_remlink(matches, nvi_to_select);
return nvi_to_select;
}
/* If we're still here, that means we didn't find any verts on selected
* fcurves. So return the head (which is also the item following
* `nvi_first_selected` if that was found). */
return BLI_pophead(matches);
}