Fix #123738: Keyframe drawing issue while duplicating keys

The issue was introduced with f06fd85d97 where the building of the keylist used was
restricted to the visible range of the dope sheet.
The optimization uses `BKE_fcurve_bezt_binarysearch_index` which can only work when
the FCurve is sorted. During transformations in the dope sheet this is not the case as the
sorting only happens when the transformation is applied.
The fix is to do a range check in the for loop instead of a binary search.
Testing the range comes with a performance impact though.

| Before optimization | broken with f06fd85d97 | this PR |
| - | - | - |
| 90ms | 6ms | 20ms |

An alternative solution would be to sort FCurves during transformations of the Dope Sheet.
This is done in the Graph Editor and with the recent speedups introduced there this could be
a viable option. However this is out of scope for this fix.

Pull Request: https://projects.blender.org/blender/blender/pulls/123824
This commit is contained in:
Christoph Lendenfeld 2024-06-27 16:50:44 +02:00 committed by Christoph Lendenfeld
parent 8945b7e49a
commit f3b393a74a

@ -1111,22 +1111,14 @@ void fcurve_to_keylist(AnimData *adt,
BezTripleChain chain = {nullptr};
int start_index = 0;
/* Used in an exclusive way. */
int end_index = fcu->totvert;
bool replace;
start_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[0], fcu->totvert, &replace);
if (start_index > 0) {
start_index--;
}
end_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[1], fcu->totvert, &replace);
if (end_index < fcu->totvert) {
end_index++;
}
/* Loop through beztriples, making ActKeysColumns. */
for (int v = start_index; v < end_index; v++) {
for (int v = 0; v < fcu->totvert; v++) {
/* Not using binary search to limit the range because the FCurve might not be sorted e.g. when
* transforming in the Dope Sheet. */
const float x = fcu->bezt[v].vec[1][0];
if (x < range[0] || x > range[1]) {
continue;
}
chain.cur = &fcu->bezt[v];
/* Neighbor columns, accounting for being cyclic. */
@ -1142,7 +1134,7 @@ void fcurve_to_keylist(AnimData *adt,
add_bezt_to_keycolumns_list(keylist, &chain);
}
update_keyblocks(keylist, &fcu->bezt[start_index], end_index - start_index);
update_keyblocks(keylist, &fcu->bezt[0], fcu->totvert);
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, fcu, true, false);