Anim: add layered Action support to BKE_animdata_transfer_by_basepath
Add explicit handling of slots to `BKE_animdata_transfer_by_basepath()`, and modernise the code to use the new API. No functional changes for legacy Actions. Ref: #123424 Pull Request: https://projects.blender.org/blender/blender/pulls/128088
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_path.hh"
|
||||
|
||||
#include "ANIM_action_iterators.hh"
|
||||
#include "ANIM_action_legacy.hh"
|
||||
|
||||
#include "CLG_log.h"
|
||||
@@ -625,12 +626,12 @@ static void animpath_update_basepath(FCurve *fcu,
|
||||
* F-Curves to need to be moved over too
|
||||
*/
|
||||
static void action_move_fcurves_by_basepath(bAction *srcAct,
|
||||
const animrig::slot_handle_t src_slot_handle,
|
||||
bAction *dstAct,
|
||||
const animrig::slot_handle_t dst_slot_handle,
|
||||
const char *src_basepath,
|
||||
const char *dst_basepath)
|
||||
{
|
||||
FCurve *fcu, *fcn = nullptr;
|
||||
|
||||
/* sanity checks */
|
||||
if (ELEM(nullptr, srcAct, dstAct, src_basepath, dst_basepath)) {
|
||||
if (G.debug & G_DEBUG) {
|
||||
@@ -645,72 +646,22 @@ static void action_move_fcurves_by_basepath(bAction *srcAct,
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear 'temp' flags on all groups in src, as we'll be needing them later
|
||||
* to identify groups that we've managed to empty out here
|
||||
*/
|
||||
action_groups_clear_tempflags(srcAct);
|
||||
animrig::Action &source_action = srcAct->wrap();
|
||||
animrig::Action &dest_action = dstAct->wrap();
|
||||
|
||||
/* iterate over all src F-Curves, moving over the ones that need to be moved */
|
||||
for (fcu = static_cast<FCurve *>(srcAct->curves.first); fcu; fcu = fcn) {
|
||||
/* store next pointer in case we move stuff */
|
||||
fcn = fcu->next;
|
||||
|
||||
/* should F-Curve be moved over?
|
||||
* - we only need the start of the path to match basepath
|
||||
*/
|
||||
if (animpath_matches_basepath(fcu->rna_path, src_basepath)) {
|
||||
bActionGroup *agrp = nullptr;
|
||||
|
||||
/* if grouped... */
|
||||
if (fcu->grp) {
|
||||
/* make sure there will be a matching group on the other side for the migrants */
|
||||
agrp = BKE_action_group_find_name(dstAct, fcu->grp->name);
|
||||
|
||||
if (agrp == nullptr) {
|
||||
/* add a new one with a similar name (usually will be the same though) */
|
||||
agrp = action_groups_add_new(dstAct, fcu->grp->name);
|
||||
}
|
||||
|
||||
/* old groups should be tagged with 'temp' flags so they can be removed later
|
||||
* if we remove everything from them
|
||||
*/
|
||||
fcu->grp->flag |= AGRP_TEMP;
|
||||
}
|
||||
|
||||
/* perform the migration now */
|
||||
action_groups_remove_channel(srcAct, fcu);
|
||||
|
||||
animpath_update_basepath(fcu, src_basepath, dst_basepath);
|
||||
|
||||
if (agrp) {
|
||||
action_groups_add_channel(dstAct, agrp, fcu);
|
||||
}
|
||||
else {
|
||||
BLI_addtail(&dstAct->curves, fcu);
|
||||
}
|
||||
/* Get a list of all F-Curves to move. This is done in a separate step so we
|
||||
* don't move the curves while iterating over them at the same time. */
|
||||
Vector<FCurve *> fcurves_to_move;
|
||||
animrig::foreach_fcurve_in_action_slot(source_action, src_slot_handle, [&](FCurve &fcurve) {
|
||||
if (animpath_matches_basepath(fcurve.rna_path, src_basepath)) {
|
||||
fcurves_to_move.append(&fcurve);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* cleanup groups (if present) */
|
||||
if (srcAct->groups.first) {
|
||||
bActionGroup *agrp, *grp = nullptr;
|
||||
|
||||
for (agrp = static_cast<bActionGroup *>(srcAct->groups.first); agrp; agrp = grp) {
|
||||
grp = agrp->next;
|
||||
|
||||
/* only tagged groups need to be considered - clearing these tags or removing them */
|
||||
if (agrp->flag & AGRP_TEMP) {
|
||||
/* if group is empty and tagged, then we can remove as this operation
|
||||
* moved out all the channels that were formerly here
|
||||
*/
|
||||
if (BLI_listbase_is_empty(&agrp->channels)) {
|
||||
BLI_freelinkN(&srcAct->groups, agrp);
|
||||
}
|
||||
else {
|
||||
agrp->flag &= ~AGRP_TEMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Move the curves from one Action to the other, and change its path to match the destination. */
|
||||
for (FCurve *fcurve_to_move : fcurves_to_move) {
|
||||
animpath_update_basepath(fcurve_to_move, src_basepath, dst_basepath);
|
||||
animrig::action_fcurve_move(dest_action, dst_slot_handle, source_action, *fcurve_to_move);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,16 +722,22 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
|
||||
/* Set up an action if necessary, and name it in a similar way so that it
|
||||
* can be easily found again. */
|
||||
if (!dstAdt->action) {
|
||||
bAction *new_action = BKE_action_add(bmain, srcAdt->action->id.name + 2);
|
||||
/* Reduce user count to 0 as the Action is unused before it's assigned. */
|
||||
id_us_min(&new_action->id);
|
||||
animrig::assign_action(new_action, dst_owned_adt);
|
||||
animrig::Action &new_action = animrig::action_add(*bmain, srcAdt->action->id.name + 2);
|
||||
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
|
||||
new_action.slot_add_for_id(*dstID);
|
||||
}
|
||||
animrig::assign_action(&new_action, dst_owned_adt);
|
||||
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
|
||||
BLI_assert(dstAdt->slot_handle != animrig::Slot::unassigned);
|
||||
}
|
||||
}
|
||||
|
||||
/* loop over base paths, trying to fix for each one... */
|
||||
LISTBASE_FOREACH (const AnimationBasePathChange *, basepath_change, basepaths) {
|
||||
action_move_fcurves_by_basepath(srcAdt->action,
|
||||
srcAdt->slot_handle,
|
||||
dstAdt->action,
|
||||
dstAdt->slot_handle,
|
||||
basepath_change->src_basepath,
|
||||
basepath_change->dst_basepath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user