Blender V5.0
deg_builder_nodes_rig.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
12
13#include <cstdlib>
14
15#include "DNA_armature_types.h"
17#include "DNA_object_types.h"
18#include "DNA_scene_types.h"
19
20#include "BLI_listbase.h"
21
22#include "BKE_action.hh"
23#include "BKE_armature.hh"
24#include "BKE_constraint.h"
25#include "BKE_lib_query.hh"
26
27#include "DEG_depsgraph.hh"
29
34
35namespace blender::deg {
36
38 bPoseChannel *pchan,
39 int pchan_index)
40{
41 /* Pull indirect dependencies via constraints. */
43 data.builder = this;
45
46 /* Create node for constraint stack. */
47 Scene *scene_cow = get_cow_datablock(scene_);
48 Object *object_cow = get_cow_datablock(object);
49 add_operation_node(&object->id,
51 pchan->name,
53 [scene_cow, object_cow, pchan_index](::Depsgraph *depsgraph) {
54 BKE_pose_constraints_evaluate(
55 depsgraph, scene_cow, object_cow, pchan_index);
56 });
57}
58
60{
62
63 /* Find the chain's root. */
65 if (rootchan == nullptr) {
66 return;
67 }
68
71 {
72 return;
73 }
74
75 int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
76 BLI_assert(rootchan_index != -1);
77
78 /* Operation node for evaluating/running IK Solver. */
79 Scene *scene_cow = get_cow_datablock(scene_);
80 Object *object_cow = get_cow_datablock(object);
81 add_operation_node(&object->id,
83 rootchan->name,
85 [scene_cow, object_cow, rootchan_index](::Depsgraph *depsgraph) {
86 BKE_pose_iktree_evaluate(depsgraph, scene_cow, object_cow, rootchan_index);
87 });
88}
89
91 bPoseChannel *pchan,
92 bConstraint *con)
93{
95
96 /* Find the chain's root. */
98
101 {
102 return;
103 }
104
105 /* Operation node for evaluating/running Spline IK Solver.
106 * Store the "root bone" of this chain in the solver, so it knows where to
107 * start. */
108 int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
109 BLI_assert(rootchan_index != -1);
110
111 Scene *scene_cow = get_cow_datablock(scene_);
112 Object *object_cow = get_cow_datablock(object);
113 add_operation_node(&object->id,
115 rootchan->name,
117 [scene_cow, object_cow, rootchan_index](::Depsgraph *depsgraph) {
118 BKE_pose_splineik_evaluate(
119 depsgraph, scene_cow, object_cow, rootchan_index);
120 });
121}
122
123/* Pose/Armature Bones Graph */
125{
126 bArmature *armature = (bArmature *)object->data;
127 Scene *scene_cow = get_cow_datablock(scene_);
128 Object *object_cow = get_cow_datablock(object);
129 OperationNode *op_node;
130 /* Animation and/or drivers linking pose-bones to base-armature used to define them.
131 *
132 * NOTE: AnimData here is really used to control animated deform properties,
133 * which ideally should be able to be unique across different
134 * instances. Eventually, we need some type of proxy/isolation
135 * mechanism in-between here to ensure that we can use same rig
136 * multiple times in same scene. */
137 /* Armature. */
138 build_armature(armature);
139 /* Rebuild pose if not up to date. */
140 if (object->pose == nullptr || (object->pose->flag & POSE_RECALC)) {
141 /* By definition, no need to tag depsgraph as dirty from here, so we can pass nullptr bmain. */
142 BKE_pose_rebuild(nullptr, object, armature, true);
143 }
144 /* Speed optimization for animation lookups. */
145 if (object->pose != nullptr) {
149 }
150 }
171 /* Pose eval context. */
172 op_node = add_operation_node(&object->id,
175 [scene_cow, object_cow](::Depsgraph *depsgraph) {
176 BKE_pose_eval_init(depsgraph, scene_cow, object_cow);
177 });
178 op_node->set_as_entry();
179
180 op_node = add_operation_node(&object->id,
183 [scene_cow, object_cow](::Depsgraph *depsgraph) {
184 BKE_pose_eval_init_ik(depsgraph, scene_cow, object_cow);
185 });
186
187 add_operation_node(&object->id,
190 [scene_cow, object_cow](::Depsgraph *depsgraph) {
191 BKE_pose_eval_cleanup(depsgraph, scene_cow, object_cow);
192 });
193
194 op_node = add_operation_node(
195 &object->id,
198 [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_done(depsgraph, object_cow); });
199 op_node->set_as_exit();
200 /* Bones. */
201 int pchan_index = 0;
202 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
203 /* Node for bone evaluation. */
204 op_node = add_operation_node(
205 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
206 op_node->set_as_entry();
207
208 add_operation_node(&object->id,
210 pchan->name,
212 [scene_cow, object_cow, pchan_index](::Depsgraph *depsgraph) {
213 BKE_pose_eval_bone(depsgraph, scene_cow, object_cow, pchan_index);
214 });
215
216 /* NOTE: Dedicated noop for easier relationship construction. */
218
219 op_node = add_operation_node(&object->id,
221 pchan->name,
223 [object_cow, pchan_index](::Depsgraph *depsgraph) {
224 BKE_pose_bone_done(depsgraph, object_cow, pchan_index);
225 });
226
227 /* B-Bone shape computation - the real last step if present. */
228 if (check_pchan_has_bbone(object, pchan)) {
229 op_node = add_operation_node(&object->id,
231 pchan->name,
233 [object_cow, pchan_index](::Depsgraph *depsgraph) {
234 BKE_pose_eval_bbone_segments(
235 depsgraph, object_cow, pchan_index);
236 });
237 }
238
239 op_node->set_as_exit();
240
241 /* Custom properties. */
242 bool add_idprops_operation = false;
243 if (pchan->prop != nullptr) {
244 build_idproperties(pchan->prop);
245 add_idprops_operation = true;
246 }
247 if (pchan->system_properties != nullptr) {
248 build_idproperties(pchan->system_properties);
249 add_idprops_operation = true;
250 }
251 if (add_idprops_operation) {
253 &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, nullptr, pchan->name);
254 }
255 /* Build constraints. */
256 if (pchan->constraints.first != nullptr) {
257 build_pose_constraints(object, pchan, pchan_index);
258 }
270 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
271 switch (con->type) {
273 build_ik_pose(object, pchan, con);
274 break;
275
277 build_splineik_pose(object, pchan, con);
278 break;
279
280 default:
281 break;
282 }
283 }
284 /* Custom shape. */
285 if (pchan->custom != nullptr) {
286 /* NOTE: The relation builder will ensure visibility of the custom shape object. */
287 build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY, false);
288 }
289 pchan_index++;
290 }
291}
292
293} // namespace blender::deg
Blender kernel action and pose functionality.
void BKE_pose_update_constraint_flags(bPose *pose) ATTR_NONNULL(1)
void BKE_pose_channels_hash_ensure(bPose *pose) ATTR_NONNULL(1)
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
bPoseChannel * BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data)
bPoseChannel * BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, bSplineIKConstraint *data)
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, const int flag, void *userdata)
@ IDWALK_NOP
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
@ POSE_CONSTRAINTS_NEED_UPDATE_FLAGS
@ POSE_RECALC
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
Object is a sort of wrapper for general info.
BMesh const char void * data
BPy_StructRNA * depsgraph
virtual bool check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan)
virtual void build_pose_constraints(Object *object, bPoseChannel *pchan, int pchan_index)
virtual void build_object(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state, bool is_visible)
OperationNode * add_operation_node(ComponentNode *comp_node, OperationCode opcode, const DepsEvalOperationCb &op=nullptr, const char *name="", int name_tag=-1)
static void constraint_walk(bConstraint *constraint, ID **idpoin, bool is_reference, void *user_data)
virtual void build_armature(bArmature *armature)
T * get_cow_datablock(const T *orig) const
virtual void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
virtual void build_rig(Object *object)
virtual void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
virtual void build_idproperties(IDProperty *id_property)
bool has_operation_node(ID *id, NodeType comp_type, const char *comp_name, OperationCode opcode, const char *name="", int name_tag=-1)
@ DEG_ID_LINKED_INDIRECTLY
struct bPose * pose
ListBase chanbase