Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSybren A. Stüvel <sybren>2021-07-06 15:36:27 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2021-07-09 12:21:12 +0300
commitc04cceb40ed5574dcba8a55cfe97a1132c869895 (patch)
treeec136545e587ee4443fef8d7ea85673b5c37597b /source/blender/blenkernel/intern/action.c
parentb69ab42982a1da921ea9f585fceca1a53589de79 (diff)
Fix T89435: Reordering FCurves can cause crash or corruption
Correctly reset `prev` and `next` pointers of action group FCurves when separating them into distinct `ListBase`s per `bActionGroup`. These `NULL` pointers are necessary to temporarily demarcate the start & end of the `bActionGroup::channels` list. Having them still point to other FCurves caused ordering issues when moving curves towards the start/end of a group. This commit corrects the above issue and adds versioning code to rectify any ordering issues that may have been caused. For this purpose the `BKE_action_groups_reconstruct()` function is rewritten to avoid relying on the `bAction::curves` list order or `prev` link integrity. Differential Revision: https://developer.blender.org/D11811
Diffstat (limited to 'source/blender/blenkernel/intern/action.c')
-rw-r--r--source/blender/blenkernel/intern/action.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 13ca5ecf23c..d55f023d209 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -497,9 +497,8 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
}
/* Reconstruct group channel pointers.
- * Assumes that the channels are still in the proper order, i.e. that channels of the same group
- * are adjacent in the act->channels list. It also assumes that the groups
- * referred to by the FCurves are already in act->groups.
+ * Assumes that the groups referred to by the FCurves are already in act->groups.
+ * Reorders the main channel list to match group order.
*/
void BKE_action_groups_reconstruct(bAction *act)
{
@@ -514,23 +513,30 @@ void BKE_action_groups_reconstruct(bAction *act)
BLI_listbase_clear(&group->channels);
}
- bActionGroup *grp;
- bActionGroup *last_grp = NULL;
- LISTBASE_FOREACH (FCurve *, fcurve, &act->curves) {
- if (fcurve->grp == NULL) {
- continue;
- }
+ /* Sort the channels into the group lists, destroying the act->curves list. */
+ ListBase ungrouped = {NULL, NULL};
- grp = fcurve->grp;
- if (last_grp != grp) {
- /* If this is the first time we see this group, this must be the first channel. */
- grp->channels.first = fcurve;
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcurve, &act->curves) {
+ if (fcurve->grp) {
+ BLI_assert(BLI_findindex(&act->groups, fcurve->grp) >= 0);
+
+ BLI_addtail(&fcurve->grp->channels, fcurve);
+ }
+ else {
+ BLI_addtail(&ungrouped, fcurve);
}
+ }
+
+ /* Recombine into the main list. */
+ BLI_listbase_clear(&act->curves);
- /* This is the last channel, until it's overwritten by a later iteration. */
- grp->channels.last = fcurve;
- last_grp = grp;
+ LISTBASE_FOREACH (bActionGroup *, group, &act->groups) {
+ /* Copy the list header to preserve the pointers in the group. */
+ ListBase tmp = group->channels;
+ BLI_movelisttolist(&act->curves, &tmp);
}
+
+ BLI_movelisttolist(&act->curves, &ungrouped);
}
/* Remove the given channel from all groups */