Fix: Dope Sheet drawing doesn't draw connecting line outside of viewport

The issue was caused by blender/blender@f3b393a74a
Before that commit, the keylist would be built including 1 keyframe
outside the range on each side (if there was one).
After that those would be ignored, leading to the following issue

Fixes #125861

The fix is to ensure the keylist is built with 1 key outside the given range.

Pull Request: https://projects.blender.org/blender/blender/pulls/125807
This commit is contained in:
Christoph Lendenfeld
2024-08-06 12:26:33 +02:00
committed by Christoph Lendenfeld
parent 9e0b673467
commit 07f88ddd67
2 changed files with 54 additions and 14 deletions

View File

@@ -1095,6 +1095,25 @@ void cachefile_to_keylist(bDopeSheet *ads,
ANIM_animdata_freelist(&anim_data);
}
static inline void set_up_beztriple_chain(BezTripleChain &chain,
const FCurve *fcu,
const int key_index,
const bool do_extremes,
const bool is_cyclic)
{
chain.cur = &fcu->bezt[key_index];
/* Neighbor columns, accounting for being cyclic. */
if (do_extremes) {
chain.prev = (key_index > 0) ? &fcu->bezt[key_index - 1] :
is_cyclic ? &fcu->bezt[fcu->totvert - 2] :
nullptr;
chain.next = (key_index + 1 < fcu->totvert) ? &fcu->bezt[key_index + 1] :
is_cyclic ? &fcu->bezt[1] :
nullptr;
}
}
void fcurve_to_keylist(AnimData *adt,
FCurve *fcu,
AnimKeylist *keylist,
@@ -1118,32 +1137,52 @@ void fcurve_to_keylist(AnimData *adt,
* for the case that no keyframes get added to the key-columns, which happens when the given
* range doesn't overlap with the existing keyframes. */
blender::Bounds<int> index_bounds(int(fcu->totvert), 0);
/* The following is used to find the keys that are JUST outside the range. This is done so
* drawing in the dope sheet can create lines that extend off-screen. */
float left_outside_key_x = -FLT_MAX;
float right_outside_key_x = FLT_MAX;
int left_outside_key_index = -1;
int right_outside_key_index = -1;
/* Loop through beztriples, making ActKeysColumns. */
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 > left_outside_key_x) {
left_outside_key_x = x;
left_outside_key_index = v;
}
if (x > range[1] && x < right_outside_key_x) {
right_outside_key_x = x;
right_outside_key_index = v;
}
if (x < range[0] || x > range[1]) {
continue;
}
blender::math::min_max(v, index_bounds.min, index_bounds.max);
chain.cur = &fcu->bezt[v];
/* Neighbor columns, accounting for being cyclic. */
if (do_extremes) {
chain.prev = (v > 0) ? &fcu->bezt[v - 1] :
is_cyclic ? &fcu->bezt[fcu->totvert - 2] :
nullptr;
chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] :
is_cyclic ? &fcu->bezt[1] :
nullptr;
}
set_up_beztriple_chain(chain, fcu, v, do_extremes, is_cyclic);
add_bezt_to_keycolumns_list(keylist, &chain);
}
if (!index_bounds.is_empty()) {
update_keyblocks(keylist, &fcu->bezt[index_bounds.min], index_bounds.max - index_bounds.min);
if (left_outside_key_index >= 0) {
set_up_beztriple_chain(chain, fcu, left_outside_key_index, do_extremes, is_cyclic);
add_bezt_to_keycolumns_list(keylist, &chain);
/* Checking min and max because the FCurve might not be sorted. */
index_bounds.min = blender::math::min(index_bounds.min, left_outside_key_index);
index_bounds.max = blender::math::max(index_bounds.max, left_outside_key_index);
}
if (right_outside_key_index >= 0) {
set_up_beztriple_chain(chain, fcu, right_outside_key_index, do_extremes, is_cyclic);
add_bezt_to_keycolumns_list(keylist, &chain);
index_bounds.min = blender::math::min(index_bounds.min, right_outside_key_index);
index_bounds.max = blender::math::max(index_bounds.max, right_outside_key_index);
}
/* Not using index_bounds.is_empty() because that returns true if min and max are the same. That
* is a valid configuration in this case though. */
if (index_bounds.min <= index_bounds.max) {
update_keyblocks(
keylist, &fcu->bezt[index_bounds.min], (index_bounds.max + 1) - index_bounds.min);
}
if (adt) {

View File

@@ -158,7 +158,8 @@ int64_t ED_keylist_array_len(const AnimKeylist *keylist);
/**
* Add the keyframes of the F-Curve to the keylist.
* \param adt: can be a nullptr.
* \param range: only adds keys in the given range to the keylist.
* \param range: adds keys in the given range to the keylist plus 1 extra on each side if
* available.
*/
void fcurve_to_keylist(
AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int saction_flag, blender::float2 range);