Animation: correct active track/strip pointers after copying NLA tracks

After copying NLA tracks from one `AnimData` to another, also ensure
that the `AnimData::act_track` and `AnimData::actstrip` pointers are
pointing to the copy rather than the original.

This is a necessary step to allow library overrides on NLA modifiers
without crashing Blender.

The remapping of the pointers is done by looping over the tracks/strips
and comparing pointers. Alternatively, I could update the copy functions
themselves to keep track of those pointers and return them, but IMO that
would produce more spaghetti (they're also used in cases where this
pointer-remapping is not desired).
This commit is contained in:
Sybren A. Stüvel 2021-05-04 16:19:51 +02:00
parent 191664acd2
commit 46d56bd956
Notes: blender-bot 2023-02-14 09:33:11 +01:00
Referenced by issue #93707, Dragging the NLA strip cause a crash, if the related action is in tweakmode
3 changed files with 58 additions and 3 deletions

View File

@ -58,7 +58,14 @@ struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain,
struct NlaTrack *nlt,
const bool use_same_actions,
const int flag);
void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, ListBase *src, const int flag);
void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, const ListBase *src, const int flag);
/* Copy NLA tracks from #adt_source to #adt_dest, and update the active track/strip pointers to
* point at those copies. */
void BKE_nla_tracks_copy_from_adt(struct Main *bmain,
struct AnimData *adt_dest,
const struct AnimData *adt_source,
int flag);
struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
struct NlaTrack *prev,

View File

@ -354,7 +354,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
}
/* duplicate NLA data */
BKE_nla_tracks_copy(bmain, &dadt->nla_tracks, &adt->nla_tracks, flag);
BKE_nla_tracks_copy_from_adt(bmain, dadt, adt, flag);
/* duplicate drivers (F-Curves) */
BKE_fcurves_copy(&dadt->drivers, &adt->drivers);

View File

@ -254,7 +254,7 @@ NlaTrack *BKE_nlatrack_copy(Main *bmain,
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
* flags in BKE_lib_id.h
*/
void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src, const int flag)
void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, const ListBase *src, const int flag)
{
NlaTrack *nlt, *nlt_d;
@ -275,6 +275,54 @@ void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src, const int fl
}
}
/* Set adt_dest->actstrip to the strip with the same index as adt_source->actstrip. */
static void update_active_strip(AnimData *adt_dest,
NlaTrack *track_dest,
const AnimData *adt_source,
NlaTrack *track_source)
{
BLI_assert(BLI_listbase_count(&track_source->strips) == BLI_listbase_count(&track_dest->strips));
NlaStrip *strip_dest = track_dest->strips.first;
LISTBASE_FOREACH (NlaStrip *, strip_source, &track_source->strips) {
if (strip_source == adt_source->actstrip) {
adt_dest->actstrip = strip_dest;
}
strip_dest = strip_dest->next;
}
}
/* Set adt_dest->act_track to the track with the same index as adt_source->act_track. */
static void update_active_track(AnimData *adt_dest, const AnimData *adt_source)
{
BLI_assert(BLI_listbase_count(&adt_source->nla_tracks) ==
BLI_listbase_count(&adt_dest->nla_tracks));
NlaTrack *track_dest = adt_dest->nla_tracks.first;
LISTBASE_FOREACH (NlaTrack *, track_source, &adt_source->nla_tracks) {
if (track_source == adt_source->act_track) {
adt_dest->act_track = track_dest;
/* Assumption: the active strip is on the active track. */
update_active_strip(adt_dest, track_dest, adt_source, track_source);
}
track_dest = track_dest->next;
}
}
void BKE_nla_tracks_copy_from_adt(Main *bmain,
AnimData *adt_dest,
const AnimData *adt_source,
const int flag)
{
adt_dest->act_track = NULL;
adt_dest->actstrip = NULL;
BKE_nla_tracks_copy(bmain, &adt_dest->nla_tracks, &adt_source->nla_tracks, flag);
update_active_track(adt_dest, adt_source);
}
/* Adding ------------------------------------------- */
/* Add a NLA Track to the given AnimData