Fix #110108: NLA absolute snapping

Before this patch the following snapping options were broken

* snap to markers
* snap to seconds with "Absolute Time Snap" turned on
* technically also snap to Frames with "Absolute Time Snap"
turned on (but made no real difference)

The issue was that each end of the strip would snap individually.
Potentially collapsing the strip.
This would happen e.g. when snapping to markers but with only 1 marker present.

This PR fixes the issue by finding out the closest snap offset and
shifting the strip as a whole by that amount.
That means either the start or the end of the strip will snap to the target.
By doing it that way the length of the strip is never changed by snapping.

This means when snapping to Seconds with "Absolute Time Snap" turned on,
the start of the strip might not be on a full second when the end is.

Pull Request: https://projects.blender.org/blender/blender/pulls/111984
This commit is contained in:
Christoph Lendenfeld 2023-09-15 09:52:40 +02:00 committed by Christoph Lendenfeld
parent 4790c6ac61
commit bd305c8d18
1 changed files with 22 additions and 3 deletions

View File

@ -660,9 +660,28 @@ static void snap_transform_data(TransInfo *t, TransDataContainer *tc)
if (t->modifiers & MOD_SNAP_INVERT) {
invert_snap(snap_mode);
}
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
transform_snap_anim_flush_data(t, td, snap_mode, td->loc);
float offset = 0;
float smallest_snap_delta = FLT_MAX;
/* In order to move the strip in a block and not each end individually,
* find the minimal snap offset first and then shift the whole strip by that amount. */
for (int i = 0; i < tc->data_len; i++) {
TransData td = tc->data[i];
float snap_value;
transform_snap_anim_flush_data(t, &td, snap_mode, &snap_value);
/* The snap_delta measures how far from the unsnapped position the value has moved. */
const float snap_delta = *td.loc - snap_value;
if (fabs(snap_delta) < fabs(smallest_snap_delta)) {
offset = snap_value - td.iloc[0];
smallest_snap_delta = snap_delta;
}
}
for (int i = 0; i < tc->data_len; i++) {
TransData td = tc->data[i];
*td.loc = td.iloc[0] + offset;
}
}