Fix #130907: Use Blender Action name as the UsdSkelAnimation name

Rather than using a default "Anim" name when exporting armature
animations, use the animation's Action name instead. Likewise use the
UsdSkelAnimation name for the Action's name during import.

Blendshapes/shapekeys still use the default "Anim" name as there's no
action for these situations.

Pull Request: https://projects.blender.org/blender/blender/pulls/131021
This commit is contained in:
Jesse Yurkovich
2024-12-04 23:43:07 +01:00
committed by Jesse Yurkovich
parent cb94b62775
commit 69c63311fa
5 changed files with 29 additions and 14 deletions

View File

@@ -304,19 +304,26 @@ void remap_blend_shape_anim(pxr::UsdStageRefPtr stage,
const pxr::SdfPath &skel_path,
const pxr::SdfPathSet &mesh_paths)
{
pxr::UsdSkelSkeleton skel = pxr::UsdSkelSkeleton::Get(stage, skel_path);
pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Get(stage, skel_path);
if (!skel) {
if (!skel_api) {
CLOG_WARN(&LOG, "Couldn't get skeleton from path %s", skel_path.GetAsString().c_str());
return;
}
/* Create the animation. */
pxr::SdfPath anim_path = skel_path.AppendChild(usdtokens::Anim);
const pxr::UsdSkelAnimation anim = pxr::UsdSkelAnimation::Define(stage, anim_path);
/* Use existing animation if possible, otherwise create a new one. */
pxr::UsdPrim anim_prim;
pxr::UsdSkelAnimation anim;
if (skel_api.GetAnimationSource(&anim_prim)) {
anim = pxr::UsdSkelAnimation(anim_prim);
}
else {
pxr::SdfPath anim_path = skel_path.AppendChild(usdtokens::Anim);
anim = pxr::UsdSkelAnimation::Define(stage, anim_path);
}
if (!anim) {
CLOG_WARN(&LOG, "Couldn't define animation at path %s", anim_path.GetAsString().c_str());
CLOG_WARN(&LOG, "Couldn't get animation under skeleton %s", skel_path.GetAsString().c_str());
return;
}

View File

@@ -27,6 +27,7 @@
#include "BKE_deform.hh"
#include "BKE_fcurve.hh"
#include "BKE_key.hh"
#include "BKE_lib_id.hh"
#include "BKE_modifier.hh"
#include "BKE_object_deform.h"
#include "BKE_report.hh"
@@ -143,6 +144,7 @@ void import_skeleton_curves(Main *bmain,
/* Create the action on the armature. */
bAction *act = blender::animrig::id_action_ensure(bmain, &arm_obj->id);
BKE_id_rename(*bmain, act->id, anim_query.GetPrim().GetName().GetText());
/* Create the curves. */

View File

@@ -4,6 +4,9 @@
#include "usd_writer_armature.hh"
#include "usd_armature_utils.hh"
#include "usd_utils.hh"
#include "ANIM_action.hh"
#include "BKE_action.hh"
@@ -19,10 +22,6 @@
#include "CLG_log.h"
static CLG_LogRef LOG = {"io.usd"};
namespace usdtokens {
static const pxr::TfToken Anim("Anim", pxr::TfToken::Immortal);
} // namespace usdtokens
/**
* Get the pose matrix for the given channel.
* The matrix is computed relative to its parent, if a parent exists.
@@ -110,7 +109,7 @@ static void initialize(const Object *obj,
if (skel_anim) {
usd_skel_api.CreateAnimationSourceRel().SetTargets(
pxr::SdfPathVector({pxr::SdfPath(usdtokens::Anim)}));
pxr::SdfPathVector({pxr::SdfPath(skel_anim.GetPath().GetName())}));
create_pose_joints(skel_anim, *obj, deform_bones, allow_unicode);
}
}
@@ -169,9 +168,15 @@ void USDArmatureWriter::do_write(HierarchyContext &context)
pxr::UsdSkelAnimation skel_anim;
const bool allow_unicode = usd_export_context_.export_params.allow_unicode;
if (usd_export_context_.export_params.export_animation) {
/* Use the action name as the animation name. */
const animrig::Action *action = animrig::get_action(context.object->id);
const pxr::TfToken anim_name(make_safe_name(action->id.name + 2, allow_unicode));
/* Create the skeleton animation primitive as a child of the skeleton. */
pxr::SdfPath anim_path = usd_export_context_.usd_path.AppendChild(usdtokens::Anim);
pxr::SdfPath anim_path = usd_export_context_.usd_path.AppendChild(anim_name);
skel_anim = pxr::UsdSkelAnimation::Define(stage, anim_path);
if (!skel_anim) {
@@ -180,7 +185,6 @@ void USDArmatureWriter::do_write(HierarchyContext &context)
}
}
const bool allow_unicode = usd_export_context_.export_params.allow_unicode;
Map<StringRef, const Bone *> *deform_map = usd_export_context_.export_params.only_deform_bones ?
&deform_map_ :
nullptr;

View File

@@ -753,6 +753,7 @@ class USDExportTest(AbstractUSDTest):
self.assertEqual(prim.GetTypeName(), "Skeleton")
prim_skel = UsdSkel.BindingAPI(prim)
anim = UsdSkel.Animation(prim_skel.GetAnimationSource())
self.assertEqual(anim.GetPrim().GetName(), "ArmatureAction_001")
self.assertEqual(anim.GetJointsAttr().Get(),
['Bone',
'Bone/Bone_001',

View File

@@ -533,6 +533,7 @@ class USDImportTest(AbstractUSDTest):
ob_arm = bpy.data.objects["column_anim_armature"]
ob_arm2_side_a = bpy.data.objects["side_a"]
ob_arm2_side_b = bpy.data.objects["side_b"]
self.assertEqual(bpy.data.objects["Armature"].animation_data.action.name, "ArmatureAction_001")
bpy.context.scene.frame_set(1)
self.assertEqual(len(ob_xform.constraints), 1)
@@ -678,7 +679,7 @@ class USDImportTest(AbstractUSDTest):
self.assertAlmostEqual(mesh_obj.vertex_groups['Elbow'].weight(
8 + i), 1.0, 2, "Unexpected weight for Elbow deform vert")
action = bpy.data.actions['SkelAction']
action = bpy.data.actions['Anim1']
# Verify the Elbow joint rotation animation.
curve_path = 'pose.bones["Elbow"].rotation_quaternion'