Anim: Fix pose library flipping with slotted Actions

Building the F-Curve cache used for pose flipping now also works with
slotted Actions. Like the pose library itself, it only considers the first
slot of the pose asset. Multi-slot pose assets are not supported.

Pull Request: https://projects.blender.org/blender/blender/pulls/128992
This commit is contained in:
Sybren A. Stüvel
2024-10-14 18:26:20 +02:00
parent ced8833d72
commit 5cdb950bef
5 changed files with 37 additions and 8 deletions

View File

@@ -49,6 +49,14 @@ ChannelBag &channelbag_ensure(Action &action);
Vector<const FCurve *> fcurves_all(const bAction *action);
Vector<FCurve *> fcurves_all(bAction *action);
/**
* Return the F-Curves for the first slot of this Action.
*
* This works for both legacy and layered Actions. For the former, it will
* return all F-Curves in the Action.
*/
Vector<FCurve *> fcurves_first_slot(bAction *action);
/**
* Return the F-Curves for this specific slot handle.
*

View File

@@ -124,6 +124,23 @@ Vector<const FCurve *> fcurves_all(const bAction *action)
const ChannelBag>(action->wrap());
}
Vector<FCurve *> fcurves_first_slot(bAction *action)
{
if (!action) {
return {};
}
Action &action_wrap = action->wrap();
if (action_wrap.is_action_legacy()) {
return fcurves_all(action);
}
if (action_wrap.slots().is_empty()) {
return {};
}
return fcurves_for_action_slot(action, action_wrap.slot(0)->handle);
}
/* Lots of template args to support transparent non-const and const versions. */
template<typename ActionType,
typename FCurveType,

View File

@@ -9,7 +9,9 @@
*/
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "DNA_curve_types.h"
struct ChannelDriver;
@@ -348,7 +350,7 @@ int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[],
/**
* Cached f-curve look-ups, use when this needs to be done many times.
*/
FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list);
FCurvePathCache *BKE_fcurve_pathcache_create(blender::Span<FCurve *> fcurves);
void BKE_fcurve_pathcache_destroy(FCurvePathCache *fcache);
FCurve *BKE_fcurve_pathcache_find(FCurvePathCache *fcache, const char rna_path[], int array_index);
/**

View File

@@ -31,6 +31,8 @@
#include "DEG_depsgraph.hh"
using namespace blender;
/* -------------------------------------------------------------------- */
/** \name Flip the Action (Armature/Pose Objects)
*
@@ -451,7 +453,8 @@ static void action_flip_pchan_rna_paths(bAction *act)
void BKE_action_flip_with_pose(bAction *act, Object *ob_arm)
{
FCurvePathCache *fcache = BKE_fcurve_pathcache_create(&act->curves);
Vector<FCurve *> fcurves = animrig::legacy::fcurves_first_slot(act);
FCurvePathCache *fcache = BKE_fcurve_pathcache_create(fcurves);
int i;
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob_arm->pose->chanbase, i) {
action_flip_pchan(ob_arm, pchan, fcache);

View File

@@ -63,14 +63,13 @@ static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
return 0;
}
FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list)
FCurvePathCache *BKE_fcurve_pathcache_create(blender::Span<FCurve *> fcurves)
{
const uint fcurve_array_len = BLI_listbase_count(list);
const uint fcurve_array_len = fcurves.size();
FCurve **fcurve_array = static_cast<FCurve **>(
MEM_mallocN(sizeof(*fcurve_array) * fcurve_array_len, __func__));
uint i;
LISTBASE_FOREACH_INDEX (FCurve *, fcu, list, i) {
fcurve_array[i] = fcu;
for (const int i : fcurves.index_range()) {
fcurve_array[i] = fcurves[i];
}
qsort(fcurve_array, fcurve_array_len, sizeof(FCurve *), fcurve_cmp_for_cache);
@@ -83,7 +82,7 @@ FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list)
/* May over reserve, harmless. */
GHash *span_from_rna_path = BLI_ghash_str_new_ex(__func__, fcurve_array_len);
uint span_index = 0;
i = 0;
uint i = 0;
while (i < fcurve_array_len) {
uint i_end;
for (i_end = i + 1; i_end < fcurve_array_len; i_end++) {