35652ebb53ee4de825b859f2744fbcb013e0929d
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations_rig.cc
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
20 /** \file
21  * \ingroup depsgraph
22  *
23  * Methods for constructing depsgraph
24  */
25
26 #include "intern/builder/deg_builder_relations.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <cstring>  /* required for STREQ later on. */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_utildefines.h"
35 #include "BLI_blenlib.h"
36
37 extern "C" {
38 #include "DNA_action_types.h"
39 #include "DNA_anim_types.h"
40 #include "DNA_armature_types.h"
41 #include "DNA_constraint_types.h"
42 #include "DNA_customdata_types.h"
43 #include "DNA_object_types.h"
44
45 #include "BKE_action.h"
46 #include "BKE_armature.h"
47 #include "BKE_constraint.h"
48 } /* extern "C" */
49
50 #include "DEG_depsgraph.h"
51 #include "DEG_depsgraph_build.h"
52
53 #include "intern/builder/deg_builder.h"
54 #include "intern/builder/deg_builder_pchanmap.h"
55 #include "intern/debug/deg_debug.h"
56 #include "intern/node/deg_node.h"
57 #include "intern/node/deg_node_component.h"
58 #include "intern/node/deg_node_operation.h"
59
60 #include "intern/depsgraph_type.h"
61
62 namespace DEG {
63
64 /* IK Solver Eval Steps */
65 void DepsgraphRelationBuilder::build_ik_pose(Object *object,
66                                              bPoseChannel *pchan,
67                                              bConstraint *con,
68                                              RootPChanMap *root_map)
69 {
70         bKinematicConstraint *data = (bKinematicConstraint *)con->data;
71         /* Attach owner to IK Solver to. */
72         bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
73         if (rootchan == NULL) {
74                 return;
75         }
76         OperationKey pchan_local_key(&object->id,
77                                      NodeType::BONE,
78                                      pchan->name,
79                                      OperationCode::BONE_LOCAL);
80         OperationKey init_ik_key(
81                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
82         OperationKey solver_key(&object->id,
83                                 NodeType::EVAL_POSE,
84                                 rootchan->name,
85                                 OperationCode::POSE_IK_SOLVER);
86         OperationKey pose_cleanup_key(
87                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
88         add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
89         add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
90         /* Never cleanup before solver is run. */
91         add_relation(solver_key,
92                      pose_cleanup_key,
93                      "IK Solver -> Cleanup",
94                      RELATION_FLAG_GODMODE);
95         /* IK target */
96         /* TODO(sergey): This should get handled as part of the constraint code. */
97         if (data->tar != NULL) {
98                 /* TODO(sergey): For until we'll store partial matrices in the
99                  * depsgraph, we create dependency between target object and pose eval
100                  * component.
101                  *
102                  * This way we ensuring the whole subtree is updated from scratch
103                  * without need of intermediate matrices. This is an overkill, but good
104                  * enough for testing IK solver. */
105                 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
106                 if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
107                         /* TODO(sergey): This is only for until granular update stores
108                          * intermediate result. */
109                         if (data->tar != object) {
110                                 /* Different armature - can just read the results. */
111                                 ComponentKey target_key(
112                                         &data->tar->id, NodeType::BONE, data->subtarget);
113                                 add_relation(target_key, pose_key, con->name);
114                         }
115                         else {
116                                 /* Same armature - we'll use the ready state only, just in case
117                                  * this bone is in the chain we're solving. */
118                                 OperationKey target_key(&data->tar->id,
119                                                         NodeType::BONE,
120                                                         data->subtarget,
121                                                         OperationCode::BONE_DONE);
122                                 add_relation(target_key, solver_key, con->name);
123                         }
124                 }
125                 else if (data->subtarget[0] &&
126                          ELEM(data->tar->type, OB_MESH, OB_LATTICE))
127                 {
128                         /* Vertex group target. */
129                         /* NOTE: for now, we don't need to represent vertex groups
130                          * separately. */
131                         ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
132                         add_relation(target_key, solver_key, con->name);
133                         add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
134                 }
135                 else {
136                         /* Standard Object Target. */
137                         ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
138                         add_relation(target_key, pose_key, con->name);
139                 }
140                 if (data->tar == object && data->subtarget[0]) {
141                         /* Prevent target's constraints from linking to anything from same
142                          * chain that it controls. */
143                         root_map->add_bone(data->subtarget, rootchan->name);
144                 }
145         }
146         /* Pole Target. */
147         /* TODO(sergey): This should get handled as part of the constraint code. */
148         if (data->poletar != NULL) {
149                 if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
150                         ComponentKey target_key(&data->poletar->id,
151                                                 NodeType::BONE,
152                                                 data->polesubtarget);
153                         add_relation(target_key, solver_key, con->name);
154                 }
155                 else if (data->polesubtarget[0] &&
156                          ELEM(data->poletar->type, OB_MESH, OB_LATTICE))
157                 {
158                         /* Vertex group target. */
159                         /* NOTE: for now, we don't need to represent vertex groups
160                          * separately. */
161                         ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
162                         add_relation(target_key, solver_key, con->name);
163                         add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
164                 }
165                 else {
166                         ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
167                         add_relation(target_key, solver_key, con->name);
168                 }
169         }
170         DEG_DEBUG_PRINTF(
171                 (::Depsgraph *)graph_,
172                 BUILD,
173                 "\nStarting IK Build: pchan = %s, target = (%s, %s), "
174                 "segcount = %d\n",
175                 pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
176         bPoseChannel *parchan = pchan;
177         /* Exclude tip from chain if needed. */
178         if (!(data->flag & CONSTRAINT_IK_TIP)) {
179                 parchan = pchan->parent;
180         }
181         root_map->add_bone(parchan->name, rootchan->name);
182         OperationKey parchan_transforms_key(&object->id, NodeType::BONE,
183                                             parchan->name, OperationCode::BONE_READY);
184         add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
185         /* Walk to the chain's root. */
186         int segcount = 0;
187         while (parchan != NULL) {
188                 /* Make IK-solver dependent on this bone's result, since it can only run
189                  * after the standard results of the bone are know. Validate links step
190                  * on the bone will ensure that users of this bone only grab the result
191                  * with IK solver results. */
192                 if (parchan != pchan) {
193                         OperationKey parent_key(&object->id,
194                                                 NodeType::BONE,
195                                                 parchan->name,
196                                                 OperationCode::BONE_READY);
197                         add_relation(parent_key, solver_key, "IK Chain Parent");
198                         OperationKey bone_done_key(&object->id,
199                                                    NodeType::BONE,
200                                                    parchan->name,
201                                                    OperationCode::BONE_DONE);
202                         add_relation(solver_key, bone_done_key, "IK Chain Result");
203                 }
204                 else {
205                         OperationKey final_transforms_key(&object->id,
206                                                           NodeType::BONE,
207                                                           parchan->name,
208                                                           OperationCode::BONE_DONE);
209                         add_relation(solver_key, final_transforms_key, "IK Solver Result");
210                 }
211                 parchan->flag |= POSE_DONE;
212                 root_map->add_bone(parchan->name, rootchan->name);
213                 /* continue up chain, until we reach target number of items. */
214                 DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
215                                  BUILD,
216                                  "  %d = %s\n",
217                                  segcount, parchan->name);
218                 /* TODO(sergey): This is an arbitrary value, which was just following
219                  * old code convention. */
220                 segcount++;
221                 if ((segcount == data->rootbone) || (segcount > 255)) {
222                         break;
223                 }
224                 parchan  = parchan->parent;
225         }
226         OperationKey pose_done_key(
227                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
228         add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
229 }
230
231 /* Spline IK Eval Steps */
232 void DepsgraphRelationBuilder::build_splineik_pose(Object *object,
233                                                    bPoseChannel *pchan,
234                                                    bConstraint *con,
235                                                    RootPChanMap *root_map)
236 {
237         bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
238         bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
239         OperationKey transforms_key(&object->id,
240                                     NodeType::BONE,
241                                     pchan->name,
242                                     OperationCode::BONE_READY);
243         OperationKey init_ik_key(&object->id,
244                                  NodeType::EVAL_POSE,
245                                  OperationCode::POSE_INIT_IK);
246         OperationKey solver_key(&object->id,
247                                 NodeType::EVAL_POSE,
248                                 rootchan->name,
249                                 OperationCode::POSE_SPLINE_IK_SOLVER);
250         OperationKey pose_cleanup_key(
251                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
252         /* Solver depends on initialization. */
253         add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
254         /* Never cleanup before solver is run. */
255         add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
256         /* Attach owner to IK Solver. */
257         add_relation(transforms_key,
258                      solver_key,
259                      "Spline IK Solver Owner",
260                      RELATION_FLAG_GODMODE);
261         /* Attach path dependency to solver. */
262         if (data->tar != NULL) {
263                 ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
264                 add_relation(target_key, init_ik_key, "Curve.Path -> Spline IK");
265         }
266         pchan->flag |= POSE_DONE;
267         OperationKey final_transforms_key(
268                 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
269         add_relation(solver_key, final_transforms_key, "Spline IK Result");
270         root_map->add_bone(pchan->name, rootchan->name);
271         /* Walk to the chain's root/ */
272         int segcount = 0;
273         for (bPoseChannel *parchan = pchan->parent;
274              parchan != NULL;
275              parchan = parchan->parent)
276         {
277                 /* Make Spline IK solver dependent on this bone's result, since it can
278                  * only run after the standard results of the bone are know. Validate
279                  * links step on the bone will ensure that users of this bone only grab
280                  * the result with IK solver results. */
281                 if (parchan != pchan) {
282                         OperationKey parent_key(&object->id,
283                                                 NodeType::BONE,
284                                                 parchan->name,
285                                                 OperationCode::BONE_READY);
286                         add_relation(parent_key, solver_key, "Spline IK Solver Update");
287                         OperationKey bone_done_key(&object->id,
288                                                    NodeType::BONE,
289                                                    parchan->name,
290                                                    OperationCode::BONE_DONE);
291                         add_relation(solver_key, bone_done_key, "IK Chain Result");
292                 }
293                 parchan->flag |= POSE_DONE;
294                 OperationKey final_transforms_key(&object->id,
295                                                   NodeType::BONE,
296                                                   parchan->name,
297                                                   OperationCode::BONE_DONE);
298                 add_relation(
299                         solver_key, final_transforms_key, "Spline IK Solver Result");
300                 root_map->add_bone(parchan->name, rootchan->name);
301                 /* TODO(sergey): This is an arbitrary value, which was just following
302                  * old code convention. */
303                 segcount++;
304                 if ((segcount == data->chainlen) || (segcount > 255)) {
305                         break;
306                 }
307         }
308         OperationKey pose_done_key(
309                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
310         add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
311 }
312
313 /* Pose/Armature Bones Graph */
314 void DepsgraphRelationBuilder::build_rig(Object *object)
315 {
316         /* Armature-Data */
317         bArmature *armature = (bArmature *)object->data;
318         // TODO: selection status?
319         /* Attach links between pose operations. */
320         ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
321         OperationKey pose_init_key(
322                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
323         OperationKey pose_init_ik_key(
324                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
325         OperationKey pose_cleanup_key(
326                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
327         OperationKey pose_done_key(
328                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
329         add_relation(
330                 local_transform, pose_init_key, "Local Transform -> Pose Init");
331         add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
332         add_relation(
333                 pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
334         /* Make sure pose is up-to-date with armature updates. */
335         build_armature(armature);
336         OperationKey armature_key(&armature->id,
337                                   NodeType::PARAMETERS,
338                                   OperationCode::ARMATURE_EVAL);
339         add_relation(armature_key, pose_init_key, "Data dependency");
340         /* Run cleanup even when there are no bones. */
341         add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup");
342         /* IK Solvers.
343          *
344          * - These require separate processing steps are pose-level to be executed
345          *   between chains of bones (i.e. once the base transforms of a bunch of
346          *   bones is done).
347          *
348          * - We build relations for these before the dependencies between operations
349          *   in the same component as it is necessary to check whether such bones
350          *   are in the same IK chain (or else we get weird issues with either
351          *   in-chain references, or with bones being parented to IK'd bones).
352          *
353          * Unsolved Issues:
354          * - Care is needed to ensure that multi-headed trees work out the same as
355          *   in ik-tree building
356          * - Animated chain-lengths are a problem. */
357         RootPChanMap root_map;
358         bool pose_depends_on_local_transform = false;
359         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
360                 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
361                         switch (con->type) {
362                                 case CONSTRAINT_TYPE_KINEMATIC:
363                                         build_ik_pose(object, pchan, con, &root_map);
364                                         pose_depends_on_local_transform = true;
365                                         break;
366                                 case CONSTRAINT_TYPE_SPLINEIK:
367                                         build_splineik_pose(object, pchan, con, &root_map);
368                                         pose_depends_on_local_transform = true;
369                                         break;
370                                 /* Constraints which needs world's matrix for transform.
371                                  * TODO(sergey): More constraints here? */
372                                 case CONSTRAINT_TYPE_ROTLIKE:
373                                 case CONSTRAINT_TYPE_SIZELIKE:
374                                 case CONSTRAINT_TYPE_LOCLIKE:
375                                 case CONSTRAINT_TYPE_TRANSLIKE:
376                                         /* TODO(sergey): Add used space check. */
377                                         pose_depends_on_local_transform = true;
378                                         break;
379                                 default:
380                                         break;
381                         }
382                 }
383         }
384         // root_map.print_debug();
385         if (pose_depends_on_local_transform) {
386                 /* TODO(sergey): Once partial updates are possible use relation between
387                  * object transform and solver itself in it's build function. */
388                 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
389                 ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
390                 add_relation(local_transform_key, pose_key, "Local Transforms");
391         }
392         /* Links between operations for each bone. */
393         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
394                 OperationKey bone_local_key(&object->id,
395                                             NodeType::BONE,
396                                             pchan->name,
397                                             OperationCode::BONE_LOCAL);
398                 OperationKey bone_pose_key(&object->id,
399                                            NodeType::BONE,
400                                            pchan->name,
401                                            OperationCode::BONE_POSE_PARENT);
402                 OperationKey bone_ready_key(&object->id,
403                                             NodeType::BONE,
404                                             pchan->name,
405                                             OperationCode::BONE_READY);
406                 OperationKey bone_done_key(&object->id,
407                                            NodeType::BONE,
408                                            pchan->name,
409                                            OperationCode::BONE_DONE);
410                 pchan->flag &= ~POSE_DONE;
411                 /* Pose init to bone local. */
412                 add_relation(pose_init_key,
413                              bone_local_key,
414                              "Pose Init - Bone Local",
415                              RELATION_FLAG_GODMODE);
416                 /* Local to pose parenting operation. */
417                 add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
418                 /* Parent relation. */
419                 if (pchan->parent != NULL) {
420                         OperationCode parent_key_opcode;
421                         /* NOTE: this difference in handling allows us to prevent lockups
422                          * while ensuring correct poses for separate chains. */
423                         if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
424                                 parent_key_opcode = OperationCode::BONE_READY;
425                         }
426                         else {
427                                 parent_key_opcode = OperationCode::BONE_DONE;
428                         }
429
430                         OperationKey parent_key(&object->id,
431                                                 NodeType::BONE,
432                                                 pchan->parent->name,
433                                                 parent_key_opcode);
434                         add_relation(
435                                 parent_key, bone_pose_key, "Parent Bone -> Child Bone");
436                 }
437                 /* Build constraints. */
438                 if (pchan->constraints.first != NULL) {
439                         /* Build relations for indirectly linked objects. */
440                         BuilderWalkUserData data;
441                         data.builder = this;
442                         BKE_constraints_id_loop(
443                                 &pchan->constraints, constraint_walk, &data);
444                         /* Constraints stack and constraint dependencies. */
445                         build_constraints(&object->id,
446                                           NodeType::BONE,
447                                           pchan->name,
448                                           &pchan->constraints,
449                                           &root_map);
450                         /* Pose -> constraints. */
451                         OperationKey constraints_key(&object->id,
452                                                      NodeType::BONE,
453                                                      pchan->name,
454                                                      OperationCode::BONE_CONSTRAINTS);
455                         add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack");
456                         add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack");
457                         /* Constraints -> ready/ */
458                         /* TODO(sergey): When constraint stack is exploded, this step should
459                          * occur before the first IK solver.  */
460                         add_relation(
461                                 constraints_key, bone_ready_key, "Constraints -> Ready");
462                 }
463                 else {
464                         /* Pose -> Ready */
465                         add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
466                 }
467                 /* Bone ready -> Bone done.
468                  * NOTE: For bones without IK, this is all that's needed.
469                  *       For IK chains however, an additional rel is created from IK
470                  *       to done, with transitive reduction removing this one. */
471                 add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
472                 /* B-Bone shape is the real final step after Done if present. */
473                 if (pchan->bone != NULL && pchan->bone->segments > 1) {
474                         OperationKey bone_segments_key(&object->id,
475                                                        NodeType::BONE,
476                                                        pchan->name,
477                                                        OperationCode::BONE_SEGMENTS);
478                         /* B-Bone shape depends on the final position of the bone. */
479                         add_relation(bone_done_key,
480                                      bone_segments_key,
481                                      "Done -> B-Bone Segments");
482                         /* B-Bone shape depends on final position of handle bones. */
483                         bPoseChannel *prev, *next;
484                         BKE_pchan_bbone_handles_get(pchan, &prev, &next);
485                         if (prev) {
486                                 OperationKey prev_key(&object->id,
487                                                       NodeType::BONE,
488                                                       prev->name,
489                                                       OperationCode::BONE_DONE);
490                                 add_relation(prev_key,
491                                              bone_segments_key,
492                                              "Prev Handle -> B-Bone Segments");
493                         }
494                         if (next) {
495                                 OperationKey next_key(&object->id,
496                                                       NodeType::BONE,
497                                                       next->name,
498                                                       OperationCode::BONE_DONE);
499                                 add_relation(next_key,
500                                              bone_segments_key,
501                                              "Next Handle -> B-Bone Segments");
502                         }
503                         /* Pose requires the B-Bone shape. */
504                         add_relation(bone_segments_key,
505                                      pose_done_key,
506                                      "PoseEval Result-Bone Link",
507                                      RELATION_FLAG_GODMODE);
508                         add_relation(bone_segments_key,
509                                      pose_cleanup_key,
510                                      "Cleanup dependency");
511                 }
512                 else {
513                         /* Assume that all bones must be done for the pose to be ready
514                          * (for deformers). */
515                         add_relation(bone_done_key,
516                                      pose_done_key,
517                                      "PoseEval Result-Bone Link");
518
519                         /* Bones must be traversed before cleanup. */
520                         add_relation(bone_done_key,
521                                      pose_cleanup_key,
522                                      "Done -> Cleanup");
523
524                         add_relation(bone_ready_key,
525                                      pose_cleanup_key,
526                                      "Ready -> Cleanup");
527                 }
528                 /* Custom shape. */
529                 if (pchan->custom != NULL) {
530                         build_object(NULL, pchan->custom);
531                 }
532         }
533 }
534
535 void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
536 {
537         bArmature *armature = (bArmature *)object->data;
538         Object *proxy_from = object->proxy_from;
539         build_armature(armature);
540         OperationKey pose_init_key(&object->id,
541                                    NodeType::EVAL_POSE,
542                                    OperationCode::POSE_INIT);
543         OperationKey pose_done_key(&object->id,
544                                    NodeType::EVAL_POSE,
545                                    OperationCode::POSE_DONE);
546         OperationKey pose_cleanup_key(&object->id,
547                                       NodeType::EVAL_POSE,
548                                       OperationCode::POSE_CLEANUP);
549         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
550                 OperationKey bone_local_key(&object->id,
551                                             NodeType::BONE, pchan->name,
552                                             OperationCode::BONE_LOCAL);
553                 OperationKey bone_ready_key(&object->id,
554                                             NodeType::BONE,
555                                             pchan->name,
556                                             OperationCode::BONE_READY);
557                 OperationKey bone_done_key(&object->id,
558                                            NodeType::BONE,
559                                            pchan->name,
560                                            OperationCode::BONE_DONE);
561                 OperationKey from_bone_done_key(&proxy_from->id,
562                                                 NodeType::BONE,
563                                                 pchan->name,
564                                                 OperationCode::BONE_DONE);
565                 add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
566                 add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
567                 add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
568                 add_relation(
569                         bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup");
570                 add_relation(bone_done_key,
571                             pose_done_key,
572                             "Bone Done -> Pose Done",
573                             RELATION_FLAG_GODMODE);
574                 /* Make sure bone in the proxy is not done before it's FROM is done. */
575                 if (pchan->bone && pchan->bone->segments > 1) {
576                         OperationKey from_bone_segments_key(&proxy_from->id,
577                                                             NodeType::BONE,
578                                                             pchan->name,
579                                                             OperationCode::BONE_SEGMENTS);
580                         add_relation(from_bone_segments_key,
581                                      bone_done_key,
582                                      "Bone Segments -> Bone Done",
583                                      RELATION_FLAG_GODMODE);
584                 }
585                 else {
586                         add_relation(from_bone_done_key,
587                                      bone_done_key,
588                                      "Bone Done -> Bone Done");
589                 }
590
591                 if (pchan->prop != NULL) {
592                         OperationKey bone_parameters(&object->id,
593                                                      NodeType::PARAMETERS,
594                                                      OperationCode::PARAMETERS_EVAL,
595                                                      pchan->name);
596                         OperationKey from_bone_parameters(&proxy_from->id,
597                                                           NodeType::PARAMETERS,
598                                                           OperationCode::PARAMETERS_EVAL,
599                                                           pchan->name);
600                         add_relation(from_bone_parameters,
601                                      bone_parameters,
602                                      "Proxy Bone Parameters");
603                 }
604         }
605 }
606
607 }  // namespace DEG