Blender  V2.93
deg_builder_relations_rig.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2013 Blender Foundation.
17  * All rights reserved.
18  */
19 
27 
28 #include <cstdio>
29 #include <cstdlib>
30 #include <cstring> /* required for STREQ later on. */
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "BLI_blenlib.h"
35 #include "BLI_utildefines.h"
36 
37 #include "DNA_action_types.h"
38 #include "DNA_anim_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_constraint_types.h"
41 #include "DNA_customdata_types.h"
42 #include "DNA_object_types.h"
43 
44 #include "BKE_action.h"
45 #include "BKE_armature.h"
46 #include "BKE_constraint.h"
47 
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_build.h"
50 
53 #include "intern/debug/deg_debug.h"
54 #include "intern/node/deg_node.h"
57 
59 #include "intern/depsgraph_type.h"
60 
61 namespace blender::deg {
62 
63 /* IK Solver Eval Steps */
65  bPoseChannel *pchan,
66  bConstraint *con,
67  RootPChanMap *root_map)
68 {
69  if ((con->flag & CONSTRAINT_DISABLE) != 0) {
70  /* Do not add disabled IK constraints to the relations. If these needs to be temporarily
71  * enabled, they will be added as temporary constraints during transform. */
72  return;
73  }
74 
76  /* Attach owner to IK Solver to. */
78  if (rootchan == nullptr) {
79  return;
80  }
81  OperationKey pchan_local_key(
82  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
84  OperationKey solver_key(
85  &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_IK_SOLVER);
87  add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
88  add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
89  /* Never cleanup before solver is run. */
90  add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup", RELATION_FLAG_GODMODE);
91  /* The ITASC solver currently accesses the target transforms in init tree :(
92  * TODO: Fix ITASC and remove this.
93  */
94  bool is_itasc = (object->pose->iksolver == IKSOLVER_ITASC);
95  OperationKey target_dependent_key = is_itasc ? init_ik_key : solver_key;
96  /* IK target */
97  /* TODO(sergey): This should get handled as part of the constraint code. */
98  if (data->tar != nullptr) {
99  /* Different object - requires its transform. */
100  if (data->tar != object) {
101  ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
102  add_relation(target_key, target_dependent_key, con->name);
103  }
104  /* Subtarget references: */
105  if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
106  /* Bone - use the final transformation. */
107  OperationKey target_key(
108  &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE);
109  add_relation(target_key, target_dependent_key, con->name);
110  }
111  else if (data->subtarget[0] && ELEM(data->tar->type, OB_MESH, OB_LATTICE)) {
112  /* Vertex group target. */
113  /* NOTE: for now, we don't need to represent vertex groups
114  * separately. */
115  ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
116  add_relation(target_key, target_dependent_key, con->name);
118  }
119  if (data->tar == object && data->subtarget[0]) {
120  /* Prevent target's constraints from linking to anything from same
121  * chain that it controls. */
122  root_map->add_bone(data->subtarget, rootchan->name);
123  }
124  }
125  /* Pole Target. */
126  /* TODO(sergey): This should get handled as part of the constraint code. */
127  if (data->poletar != nullptr) {
128  /* Different object - requires its transform. */
129  if (data->poletar != object) {
130  ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
131  add_relation(target_key, target_dependent_key, con->name);
132  }
133  /* Subtarget references: */
134  if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
135  /* Bone - use the final transformation. */
136  OperationKey target_key(
137  &data->poletar->id, NodeType::BONE, data->polesubtarget, OperationCode::BONE_DONE);
138  add_relation(target_key, target_dependent_key, con->name);
139  }
140  else if (data->polesubtarget[0] && ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) {
141  /* Vertex group target. */
142  /* NOTE: for now, we don't need to represent vertex groups
143  * separately. */
144  ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
145  add_relation(target_key, target_dependent_key, con->name);
147  }
148  }
150  BUILD,
151  "\nStarting IK Build: pchan = %s, target = (%s, %s), "
152  "segcount = %d\n",
153  pchan->name,
154  data->tar ? data->tar->id.name : "nullptr",
155  data->subtarget,
156  data->rootbone);
157  bPoseChannel *parchan = pchan;
158  /* Exclude tip from chain if needed. */
159  if (!(data->flag & CONSTRAINT_IK_TIP)) {
160  parchan = pchan->parent;
161  }
162  root_map->add_bone(parchan->name, rootchan->name);
163  OperationKey parchan_transforms_key(
164  &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
165  add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
166  /* Walk to the chain's root. */
167  int segcount = 0;
168  while (parchan != nullptr) {
169  /* Make IK-solver dependent on this bone's result, since it can only run
170  * after the standard results of the bone are know. Validate links step
171  * on the bone will ensure that users of this bone only grab the result
172  * with IK solver results. */
173  if (parchan != pchan) {
174  OperationKey parent_key(
175  &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
176  add_relation(parent_key, solver_key, "IK Chain Parent");
177  OperationKey bone_done_key(
178  &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
179  add_relation(solver_key, bone_done_key, "IK Chain Result");
180  }
181  else {
182  OperationKey final_transforms_key(
183  &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
184  add_relation(solver_key, final_transforms_key, "IK Solver Result");
185  }
186  parchan->flag |= POSE_DONE;
187  root_map->add_bone(parchan->name, rootchan->name);
188  /* continue up chain, until we reach target number of items. */
189  DEG_DEBUG_PRINTF((::Depsgraph *)graph_, BUILD, " %d = %s\n", segcount, parchan->name);
190  /* TODO(sergey): This is an arbitrary value, which was just following
191  * old code convention. */
192  segcount++;
193  if ((segcount == data->rootbone) || (segcount > 255)) {
194  break;
195  }
196  parchan = parchan->parent;
197  }
199  add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
200 
201  /* Add relation when the root of this IK chain is influenced by another IK chain. */
202  build_inter_ik_chains(object, solver_key, rootchan, root_map);
203 }
204 
205 /* Spline IK Eval Steps */
207  bPoseChannel *pchan,
208  bConstraint *con,
209  RootPChanMap *root_map)
210 {
213  OperationKey transforms_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
215  OperationKey solver_key(
216  &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_SPLINE_IK_SOLVER);
217  OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
218  /* Solver depends on initialization. */
219  add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
220  /* Never cleanup before solver is run. */
221  add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
222  /* Attach owner to IK Solver. */
223  add_relation(transforms_key, solver_key, "Spline IK Solver Owner", RELATION_FLAG_GODMODE);
224  /* Attach path dependency to solver. */
225  if (data->tar != nullptr) {
226  ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY);
227  add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK");
228  ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM);
229  add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK");
231  }
232  pchan->flag |= POSE_DONE;
233  OperationKey final_transforms_key(
234  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
235  add_relation(solver_key, final_transforms_key, "Spline IK Result");
236  root_map->add_bone(pchan->name, rootchan->name);
237  /* Walk to the chain's root/ */
238  int segcount = 1;
239  for (bPoseChannel *parchan = pchan->parent; parchan != nullptr && segcount < data->chainlen;
240  parchan = parchan->parent, segcount++) {
241  /* Make Spline IK solver dependent on this bone's result, since it can
242  * only run after the standard results of the bone are know. Validate
243  * links step on the bone will ensure that users of this bone only grab
244  * the result with IK solver results. */
245  OperationKey parent_key(&object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
246  add_relation(parent_key, solver_key, "Spline IK Solver Update");
247  OperationKey bone_done_key(
248  &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
249  add_relation(solver_key, bone_done_key, "Spline IK Solver Result");
250  parchan->flag |= POSE_DONE;
251  root_map->add_bone(parchan->name, rootchan->name);
252  }
254  add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
255 
256  /* Add relation when the root of this IK chain is influenced by another IK chain. */
257  build_inter_ik_chains(object, solver_key, rootchan, root_map);
258 }
259 
261  const OperationKey &solver_key,
262  const bPoseChannel *rootchan,
263  const RootPChanMap *root_map)
264 {
265  bPoseChannel *deepest_root = nullptr;
266  const char *root_name = rootchan->name;
267 
268  /* Find shared IK chain root. */
269  for (bPoseChannel *parchan = rootchan->parent; parchan; parchan = parchan->parent) {
270  if (!root_map->has_common_root(root_name, parchan->name)) {
271  break;
272  }
273  deepest_root = parchan;
274  }
275  if (deepest_root == nullptr) {
276  return;
277  }
278 
279  OperationKey other_bone_key(
280  &object->id, NodeType::BONE, deepest_root->name, OperationCode::BONE_DONE);
281  add_relation(other_bone_key, solver_key, "IK Chain Overlap");
282 }
283 
284 /* Pose/Armature Bones Graph */
286 {
287  /* Armature-Data */
288  bArmature *armature = (bArmature *)object->data;
289  // TODO: selection status?
290  /* Attach links between pose operations. */
291  ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
293  OperationKey pose_init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
294  OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
296  add_relation(local_transform, pose_init_key, "Local Transform -> Pose Init");
297  add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
298  add_relation(pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
299  /* Make sure pose is up-to-date with armature updates. */
300  build_armature(armature);
302  add_relation(armature_key, pose_init_key, "Data dependency");
303  /* Run cleanup even when there are no bones. */
304  add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup");
305  /* IK Solvers.
306  *
307  * - These require separate processing steps are pose-level to be executed
308  * between chains of bones (i.e. once the base transforms of a bunch of
309  * bones is done).
310  *
311  * - We build relations for these before the dependencies between operations
312  * in the same component as it is necessary to check whether such bones
313  * are in the same IK chain (or else we get weird issues with either
314  * in-chain references, or with bones being parented to IK'd bones).
315  *
316  * Unsolved Issues:
317  * - Care is needed to ensure that multi-headed trees work out the same as
318  * in ik-tree building
319  * - Animated chain-lengths are a problem. */
320  RootPChanMap root_map;
321  bool pose_depends_on_local_transform = false;
322  LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
323  LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
324  switch (con->type) {
326  build_ik_pose(object, pchan, con, &root_map);
327  pose_depends_on_local_transform = true;
328  break;
330  build_splineik_pose(object, pchan, con, &root_map);
331  pose_depends_on_local_transform = true;
332  break;
333  /* Constraints which needs world's matrix for transform.
334  * TODO(sergey): More constraints here? */
339  /* TODO(sergey): Add used space check. */
340  pose_depends_on_local_transform = true;
341  break;
342  default:
343  break;
344  }
345  }
346  }
347  // root_map.print_debug();
348  if (pose_depends_on_local_transform) {
349  /* TODO(sergey): Once partial updates are possible use relation between
350  * object transform and solver itself in its build function. */
351  ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
352  ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
353  add_relation(local_transform_key, pose_key, "Local Transforms");
354  }
355  /* Links between operations for each bone. */
356  LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
357  build_idproperties(pchan->prop);
358  OperationKey bone_local_key(
359  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
360  OperationKey bone_pose_key(
361  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_POSE_PARENT);
362  OperationKey bone_ready_key(
363  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
364  OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
365  pchan->flag &= ~POSE_DONE;
366  /* Pose init to bone local. */
367  add_relation(pose_init_key, bone_local_key, "Pose Init - Bone Local", RELATION_FLAG_GODMODE);
368  /* Local to pose parenting operation. */
369  add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
370  /* Parent relation. */
371  if (pchan->parent != nullptr) {
372  OperationCode parent_key_opcode;
373  /* NOTE: this difference in handling allows us to prevent lockups
374  * while ensuring correct poses for separate chains. */
375  if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
376  parent_key_opcode = OperationCode::BONE_READY;
377  }
378  else {
379  parent_key_opcode = OperationCode::BONE_DONE;
380  }
381 
382  OperationKey parent_key(&object->id, NodeType::BONE, pchan->parent->name, parent_key_opcode);
383  add_relation(parent_key, bone_pose_key, "Parent Bone -> Child Bone");
384  }
385  /* Build constraints. */
386  if (pchan->constraints.first != nullptr) {
387  /* Build relations for indirectly linked objects. */
388  BuilderWalkUserData data;
389  data.builder = this;
390  BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data);
391  /* Constraints stack and constraint dependencies. */
392  build_constraints(&object->id, NodeType::BONE, pchan->name, &pchan->constraints, &root_map);
393  /* Pose -> constraints. */
394  OperationKey constraints_key(
395  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_CONSTRAINTS);
396  add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack");
397  add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack");
398  /* Constraints -> ready/ */
399  /* TODO(sergey): When constraint stack is exploded, this step should
400  * occur before the first IK solver. */
401  add_relation(constraints_key, bone_ready_key, "Constraints -> Ready");
402  }
403  else {
404  /* Pose -> Ready */
405  add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
406  }
407  /* Bone ready -> Bone done.
408  * NOTE: For bones without IK, this is all that's needed.
409  * For IK chains however, an additional rel is created from IK
410  * to done, with transitive reduction removing this one. */
411  add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
412  /* B-Bone shape is the real final step after Done if present. */
413  if (check_pchan_has_bbone(object, pchan)) {
414  OperationKey bone_segments_key(
415  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
416  /* B-Bone shape depends on the final position of the bone. */
417  add_relation(bone_done_key, bone_segments_key, "Done -> B-Bone Segments");
418  /* B-Bone shape depends on final position of handle bones. */
419  bPoseChannel *prev, *next;
420  BKE_pchan_bbone_handles_get(pchan, &prev, &next);
421  if (prev) {
423  /* Inheriting parent roll requires access to prev handle's B-Bone properties. */
424  if ((pchan->bone->flag & BONE_ADD_PARENT_END_ROLL) != 0 &&
425  check_pchan_has_bbone_segments(object, prev)) {
427  }
428  OperationKey prev_key(&object->id, NodeType::BONE, prev->name, opcode);
429  add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments");
430  }
431  if (next) {
432  OperationKey next_key(&object->id, NodeType::BONE, next->name, OperationCode::BONE_DONE);
433  add_relation(next_key, bone_segments_key, "Next Handle -> B-Bone Segments");
434  }
435  /* Pose requires the B-Bone shape. */
436  add_relation(
437  bone_segments_key, pose_done_key, "PoseEval Result-Bone Link", RELATION_FLAG_GODMODE);
438  add_relation(bone_segments_key, pose_cleanup_key, "Cleanup dependency");
439  }
440  else {
441  /* Assume that all bones must be done for the pose to be ready
442  * (for deformers). */
443  add_relation(bone_done_key, pose_done_key, "PoseEval Result-Bone Link");
444 
445  /* Bones must be traversed before cleanup. */
446  add_relation(bone_done_key, pose_cleanup_key, "Done -> Cleanup");
447 
448  add_relation(bone_ready_key, pose_cleanup_key, "Ready -> Cleanup");
449  }
450  /* Custom shape. */
451  if (pchan->custom != nullptr) {
452  build_object(pchan->custom);
453  }
454  }
455 }
456 
458 {
459  bArmature *armature = (bArmature *)object->data;
460  Object *proxy_from = object->proxy_from;
461  build_armature(armature);
464  OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
465  LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
466  build_idproperties(pchan->prop);
467  OperationKey bone_local_key(
468  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
469  OperationKey bone_ready_key(
470  &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
471  OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
472  OperationKey from_bone_done_key(
473  &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
474  add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
475  add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
476  add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
477  add_relation(bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup");
478  add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done", RELATION_FLAG_GODMODE);
479  /* Make sure bone in the proxy is not done before its FROM is done. */
480  if (check_pchan_has_bbone(object, pchan)) {
481  OperationKey from_bone_segments_key(
482  &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
483  add_relation(from_bone_segments_key,
484  bone_done_key,
485  "Bone Segments -> Bone Done",
487  }
488  else {
489  add_relation(from_bone_done_key, bone_done_key, "Bone Done -> Bone Done");
490  }
491 
492  /* Parent relation: even though the proxy bone itself doesn't need
493  * the parent bone, some users expect the parent to be ready if the
494  * bone itself is (e.g. for computing the local space matrix).
495  */
496  if (pchan->parent != nullptr) {
497  OperationKey parent_key(
498  &object->id, NodeType::BONE, pchan->parent->name, OperationCode::BONE_DONE);
499  add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone");
500  }
501 
502  if (pchan->prop != nullptr) {
503  OperationKey bone_parameters(
504  &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
505  OperationKey from_bone_parameters(
506  &proxy_from->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
507  add_relation(from_bone_parameters, bone_parameters, "Proxy Bone Parameters");
508  }
509  }
510 }
511 
512 } // namespace blender::deg
Blender kernel action and pose functionality.
void BKE_pchan_bbone_handles_get(struct bPoseChannel *pchan, struct bPoseChannel **r_prev, struct bPoseChannel **r_next)
Definition: armature.c:921
struct bPoseChannel * BKE_armature_ik_solver_find_root(struct bPoseChannel *pchan, struct bKinematicConstraint *data)
Definition: armature.c:2910
struct bPoseChannel * BKE_armature_splineik_solver_find_root(struct bPoseChannel *pchan, struct bSplineIKConstraint *data)
Definition: armature.c:2931
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata)
Definition: constraint.c:5680
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define ELEM(...)
@ DAG_EVAL_NEED_CURVE_PATH
Definition: DEG_depsgraph.h:70
@ IKSOLVER_ITASC
@ POSE_DONE
@ BONE_ADD_PARENT_END_ROLL
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_SIZELIKE
#define CD_MASK_MDEFORMVERT
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_ARMATURE
@ OB_MESH
Read Guarded memory(de)allocation.
virtual bool check_pchan_has_bbone(Object *object, const bPoseChannel *pchan)
Definition: deg_builder.cc:106
virtual bool check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan)
Definition: deg_builder.cc:126
virtual void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map)
virtual void build_armature(bArmature *armature)
virtual void build_constraints(ID *id, NodeType component_type, const char *component_subdata, ListBase *constraints, RootPChanMap *root_map)
void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks)
void add_special_eval_flag(ID *id, uint32_t flag)
Relation * add_relation(const KeyFrom &key_from, const KeyTo &key_to, const char *description, int flags=0)
virtual void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map)
virtual void build_inter_ik_chains(Object *object, const OperationKey &solver_key, const bPoseChannel *rootchan, const RootPChanMap *root_map)
virtual void build_idproperties(IDProperty *id_property)
#define DEG_DEBUG_PRINTF(depsgraph, type,...)
Definition: deg_debug.h:68
static ulong * next
struct bPose * pose
struct Object * proxy_from
void * data
struct bPoseChannel * parent
ListBase chanbase
static DEGCustomDataMeshMasks MaskVert(const uint64_t vert_mask)
bool has_common_root(const char *bone1, const char *bone2) const
void add_bone(const char *bone, const char *root)