diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2020-11-30 18:12:55 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2020-11-30 18:30:44 +0300 |
commit | 8c74c35ecb5b6416fcfc624e52c068ed90f48757 (patch) | |
tree | 85cd6244d4d1984b3df73880bf4b89f8be3aae7b /source | |
parent | ed9b70393c47ecd5736c7d9ca3216e5306ca7b73 (diff) |
Fix T81628: Moving Python-made channels freezes Blender
Fix various problems in the Action Group rearranging code. All fixes are
necessary to resolve the bug.
- Before groups are rearranged, the channels are moved into their
respective groups (so no longer referenced by `action->channels`). A
temporary group is made for ungrouped channels. The code made
assumptions about the channels being in the same order as the groups;
that assumption has been removed.
- Looping over channels in an Action Group should stop when reaching the
last channel, and not until `NULL`.
- After all the reshuffling is done, the `action->channels` linked list
wasn't terminated properly. Now `first.prev` and `last.next` are set
to `NULL` to avoid infinite loops.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4c17d84b200..ba3796ad245 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1213,15 +1213,29 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp) /* Separate F-Curves into lists per group */ LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) { - if (agrp->channels.first) { - fcu = agrp->channels.last; - act->curves.first = fcu->next; + FCurve *const group_fcurves_first = agrp->channels.first; + FCurve *const group_fcurves_last = agrp->channels.last; + if (group_fcurves_first == NULL) { + /* Empty group. */ + continue; + } - fcu = agrp->channels.first; - fcu->prev = NULL; + if (group_fcurves_first == act->curves.first) { + /* First of the action curves, update the start of the action curves. */ + BLI_assert(group_fcurves_first->prev == NULL); + act->curves.first = group_fcurves_last->next; + } + else { + group_fcurves_first->prev->next = group_fcurves_last->next; + } - fcu = agrp->channels.last; - fcu->next = NULL; + if (group_fcurves_last == act->curves.last) { + /* Last of the action curves, update the end of the action curves. */ + BLI_assert(group_fcurves_last->next == NULL); + act->curves.last = group_fcurves_first->prev; + } + else { + group_fcurves_last->next->prev = group_fcurves_first->prev; } } @@ -1277,12 +1291,22 @@ static void join_groups_action_temp(bAction *act) if (agrp->flag & AGRP_TEMP) { LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) { fcu->grp = NULL; + if (fcu == agrp->channels.last) { + break; + } } BLI_remlink(&act->groups, agrp); break; } } + + /* BLI_movelisttolist() doesn't touch first->prev and last->next pointers in its "dst" list. + * Ensure that after the reshuffling the list is properly terminated. */ + FCurve *act_fcurves_first = act->curves.first; + act_fcurves_first->prev = NULL; + FCurve *act_fcurves_last = act->curves.last; + act_fcurves_last->next = NULL; } /* Change the order of anim-channels within action |