Blender V4.5
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 bArmature *armature = static_cast<bArmature *>(ob->data);
71 const blender::bke::BoneNameSet selected_bone_names =
73
74 /* Mute all FCurves that are not associated with selected bones. This separates the concept of
75 * bone selection from the FCurve evaluation code. */
76 Vector<FCurve *> modified_fcurves = pose_apply_disable_fcurves_for_unselected_bones(
77 action, slot_handle, selected_bone_names);
78
79 /* Apply the Action. */
80 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
81
82 applier(&pose_owner_ptr, action, slot_handle, anim_eval_context);
83
84 pose_apply_restore_fcurves(modified_fcurves);
85}
86
87} // namespace
88
90 bAction *action,
91 const int32_t slot_handle,
92 const AnimationEvalContext *anim_eval_context)
93{
94 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
95 animsys_evaluate_action(&pose_owner_ptr, action, slot_handle, anim_eval_context, false);
96}
97
99 bAction *action,
100 const int32_t slot_handle,
101 const AnimationEvalContext *anim_eval_context,
102 const float blend_factor)
103{
104 auto evaluate_and_blend = [blend_factor](PointerRNA *ptr,
105 bAction *act,
106 const int32_t slot_handle,
107 const AnimationEvalContext *anim_eval_context) {
108 animsys_blend_in_action(ptr, act, slot_handle, anim_eval_context, blend_factor);
109 };
110
111 pose_apply(ob, action, slot_handle, anim_eval_context, evaluate_and_blend);
112}
113
115 bAction *action,
116 slot_handle_t slot_handle,
117 const AnimationEvalContext *anim_eval_context,
118 const float blend_factor)
119{
120 PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
121 animsys_blend_in_action(&pose_owner_ptr, action, slot_handle, anim_eval_context, blend_factor);
122}
123
125{
126 for (const Object *obj : objects) {
127 if (!obj->pose) {
128 continue;
129 }
130 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &obj->pose->chanbase) {
131 if (pose_bone->bone->flag & BONE_SELECTED) {
132 return true;
133 }
134 }
135 }
136 return false;
137}
138
140 Action &pose_action,
141 const AnimationEvalContext *anim_eval_context,
142 const float blend_factor)
143{
144 if (any_bone_selected(objects)) {
145 for (Object *object : objects) {
146 Slot &slot = get_best_pose_slot_for_id(object->id, pose_action);
147 pose_apply_action_blend(object, &pose_action, slot.handle, anim_eval_context, blend_factor);
148 }
149 }
150 else {
151 /* In the case of nothing selected, act as if all is selected. This is a convenience feature
152 * for the artists so they don't have to be specific in their selection all the time. */
153 for (Object *object : objects) {
154 Slot &slot = get_best_pose_slot_for_id(object->id, pose_action);
156 object, &pose_action, slot.handle, anim_eval_context, blend_factor);
157 }
158 }
159}
160
162{
163 BLI_assert_msg(pose_data.slot_array_num > 0,
164 "Actions without slots have no data. This should have been caught earlier.");
165
166 Slot *slot = generic_slot_for_autoassign(id, pose_data, "");
167 if (slot == nullptr) {
168 slot = pose_data.slot(0);
169 }
170
171 return *slot;
172}
173
174} // 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:911
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
@ FCURVE_DISABLED
struct FCurve FCurve
@ BONE_SELECTED
struct bArmature bArmature
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:114
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:161
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)
BoneNameSet BKE_armature_find_selected_bone_names(const bArmature *armature)
blender::Set< std::string > BoneNameSet
PointerRNA RNA_id_pointer_create(ID *id)
Definition DNA_ID.h:404
struct bPose * pose
PointerRNA * ptr
Definition wm_files.cc:4226