Blender V5.0
pose.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "ANIM_pose.hh"
10#include "BKE_action.hh"
11#include "BKE_animsys.h"
12#include "BKE_armature.hh"
13#include "BLI_listbase.h"
14#include "DNA_anim_types.h"
15#include "DNA_object_types.h"
16#include "RNA_access.hh"
17
18#include "ANIM_action.hh"
19
20namespace blender::animrig {
21
22namespace {
23
24using ActionApplier = blender::FunctionRef<void(
25 PointerRNA *, bAction *, slot_handle_t, const AnimationEvalContext *)>;
26
27void pose_apply_restore_fcurves(const Span<FCurve *> fcurves)
28{
29 for (FCurve *fcu : fcurves) {
30 fcu->flag &= ~FCURVE_DISABLED;
31 }
32}
33
34/* Returns a vector of all FCurves on which the fcurve flag was modified. */
35Vector<FCurve *> pose_apply_disable_fcurves_for_unselected_bones(
36 bAction *action,
37 const slot_handle_t slot_handle,
38 const blender::bke::BoneNameSet &selected_bone_names)
39{
40 Vector<FCurve *> modified_fcurves;
41 auto disable_unselected_fcurve = [&](FCurve *fcu, const char *bone_name) {
42 const bool is_bone_selected = selected_bone_names.contains(bone_name);
43 if (!is_bone_selected) {
44 if (!(fcu->flag & FCURVE_DISABLED)) {
45 /* FCurve is not yet disabled, we need to reset that later. */
46 modified_fcurves.append(fcu);
47 }
48 fcu->flag |= FCURVE_DISABLED;
49 }
50 };
51 blender::bke::BKE_action_find_fcurves_with_bones(action, slot_handle, disable_unselected_fcurve);
52 return modified_fcurves;
53}
54
55void pose_apply(Object *ob,
56 bAction *action,
57 const slot_handle_t slot_handle,
58 const AnimationEvalContext *anim_eval_context,
59 ActionApplier applier)
60{
61 bPose *pose = ob->pose;
62 if (pose == nullptr) {
63 return;
64 }
65
66 if (action->wrap().slot_array_num == 0) {
67 return;
68 }
69
70 const blender::bke::BoneNameSet selected_bone_names =
72
73 /* Mute all FCurves that are not associated with selected bones. This separates the concept of
74 * bone selection from the FCurve evaluation code. */
75 Vector<FCurve *> modified_fcurves = pose_apply_disable_fcurves_for_unselected_bones(
76 action, slot_handle, selected_bone_names);
77
78 /* Apply the Action. */
79 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
80
81 applier(&pose_owner_ptr, action, slot_handle, anim_eval_context);
82
83 pose_apply_restore_fcurves(modified_fcurves);
84}
85
86} // namespace
87
89 bAction *action,
90 const int32_t slot_handle,
91 const AnimationEvalContext *anim_eval_context)
92{
93 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
94 animsys_evaluate_action(&pose_owner_ptr, action, slot_handle, anim_eval_context, false);
95}
96
98 bAction *action,
99 const int32_t slot_handle,
100 const AnimationEvalContext *anim_eval_context,
101 const float blend_factor)
102{
103 auto evaluate_and_blend = [blend_factor](PointerRNA *ptr,
104 bAction *act,
105 const int32_t slot_handle,
106 const AnimationEvalContext *anim_eval_context) {
107 animsys_blend_in_action(ptr, act, slot_handle, anim_eval_context, blend_factor);
108 };
109
110 pose_apply(ob, action, slot_handle, anim_eval_context, evaluate_and_blend);
111}
112
114 bAction *action,
115 slot_handle_t slot_handle,
116 const AnimationEvalContext *anim_eval_context,
117 const float blend_factor)
118{
119 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
120 animsys_blend_in_action(&pose_owner_ptr, action, slot_handle, anim_eval_context, blend_factor);
121}
122
124{
125 for (const Object *obj : objects) {
126 if (!obj->pose) {
127 continue;
128 }
129 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &obj->pose->chanbase) {
130 if (pose_bone->flag & POSE_SELECTED) {
131 return true;
132 }
133 }
134 }
135 return false;
136}
137
139 Action &pose_action,
140 const AnimationEvalContext *anim_eval_context,
141 const float blend_factor)
142{
143 if (any_bone_selected(objects)) {
144 for (Object *object : objects) {
145 Slot &slot = get_best_pose_slot_for_id(object->id, pose_action);
146 pose_apply_action_blend(object, &pose_action, slot.handle, anim_eval_context, blend_factor);
147 }
148 }
149 else {
150 /* In the case of nothing selected, act as if all is selected. This is a convenience feature
151 * for the artists so they don't have to be specific in their selection all the time. */
152 for (Object *object : objects) {
153 Slot &slot = get_best_pose_slot_for_id(object->id, pose_action);
155 object, &pose_action, slot.handle, anim_eval_context, blend_factor);
156 }
157 }
158}
159
161{
162 BLI_assert_msg(pose_data.slot_array_num > 0,
163 "Actions without slots have no data. This should have been caught earlier.");
164
165 Slot *slot = generic_slot_for_autoassign(id, pose_data, "");
166 if (slot == nullptr) {
167 slot = pose_data.slot(0);
168 }
169
170 return *slot;
171}
172
173} // namespace blender::animrig
Functions and classes to work with Actions.
Functions to work with animation poses.
Blender kernel action and pose functionality.
void animsys_blend_in_action(struct PointerRNA *ptr, struct bAction *act, int32_t action_slot_handle, const AnimationEvalContext *anim_eval_context, float blend_factor)
Definition anim_sys.cc:914
void animsys_evaluate_action(struct PointerRNA *ptr, struct bAction *act, int32_t action_slot_handle, const struct AnimationEvalContext *anim_eval_context, bool flush_to_original)
struct AnimationEvalContext AnimationEvalContext
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
struct bAction bAction
struct bPose bPose
@ POSE_SELECTED
@ FCURVE_DISABLED
struct FCurve FCurve
Object is a sort of wrapper for general info.
struct Object Object
void append(const T &value)
bool contains(const Key &key) const
Definition BLI_set.hh:310
const Slot * slot(int64_t index) const
void pose_apply_action_all_bones(Object *ob, bAction *action, slot_handle_t slot_handle, const AnimationEvalContext *anim_eval_context)
void pose_apply_action(blender::Span< Object * > objects, Action &pose_action, const AnimationEvalContext *anim_eval_context, float blend_factor)
void pose_apply_action_blend_all_bones(Object *ob, bAction *action, slot_handle_t slot_handle, const AnimationEvalContext *anim_eval_context, float blend_factor)
Definition pose.cc:113
decltype(::ActionSlot::handle) slot_handle_t
bool any_bone_selected(blender::Span< const Object * > objects)
Slot & get_best_pose_slot_for_id(const ID &id, Action &pose_data)
Definition pose.cc:160
void pose_apply_action_blend(Object *ob, bAction *action, slot_handle_t slot_handle, const AnimationEvalContext *anim_eval_context, float blend_factor)
Slot * generic_slot_for_autoassign(const ID &animated_id, Action &action, StringRefNull last_slot_identifier)
void BKE_action_find_fcurves_with_bones(bAction *action, blender::animrig::slot_handle_t slot_handle, FoundFCurveCallback callback)
blender::Set< std::string > BoneNameSet
BoneNameSet BKE_pose_channel_find_selected_names(const Object *object)
PointerRNA RNA_id_pointer_create(ID *id)
Definition DNA_ID.h:414
struct bPose * pose
PointerRNA * ptr
Definition wm_files.cc:4238